<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <!-- 基本元数据 -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据库部署报告</title>
    <!-- 外部资源引用 -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.15.4/beautify-html.min.js"></script>
    <script src="./dmData.js"></script>

    <!-- 脚本信息 -->
    <!-- 
        脚本名     : DMReport.html
        创建时间   : 2025-07-01 10:02:09
        更新时间   : 2025-07-21 15:38:18
        描述      : 达梦数据库一键安装脚本（单机/数据守护[raft主备]/DSC）
        路径      : /soft/DMReport.html
        版本      : 1.0.0
        作者      : yuanzijian(yzj@dameng.com)
        Copyright (C) 2021-2023 Zijian Yuan
    -->

    <!-- 主样式表 -->
    <style>
        /* ========== 全局基础设置 ========== */
        * {
            margin: 0;
            /* 统一清除所有元素默认外边距 */
            padding: 0;
            /* 统一清除所有元素默认内边距 */
            box-sizing: border-box;
            /* 让 padding 和 border 包含在元素总宽高内 */
            line-height: 1.6;
            /* 设置合理的行高，提升阅读体验 */
        }

        /* ========== HTML 根元素设置 ========== */
        html {
            scroll-behavior: smooth;
            /* 页面滚动平滑过渡 */
            background: linear-gradient(135deg, #0f2a4e 0%, #1d3c6d 100%);
            /* 整体背景渐变 */
        }

        /* ========== 页面主体样式 ========== */
        body {
            color: #222;
            /* 主文本颜色，深灰提升对比度和易读性 */
            min-height: 100vh;
            /* 保证 body 至少撑满整个视口高度 */
            padding: 20px;
            /* 页面内容内边距 */
            display: flex;
            /* 使用 flex 布局使内容居中 */
            justify-content: center;
            /* 水平居中容器 */
            background: linear-gradient(135deg, #0f2a4e 0%, #1d3c6d 100%);
            /* 与 html 保持一致背景 */
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            /* 现代易读字体 */
        }

        /* ========== 主容器布局 ========== */
        .container {
            display: flex;
            /* 水平排列子元素 */
            max-width: 1400px;
            /* 容器最大宽度 */
            width: 100%;
            /* 宽度自适应 */
            gap: 30px;
            /* 子元素间距 */
            align-items: flex-start;
            /* 子元素顶部对齐 */
            animation: fadeIn 0.8s ease-out;
            /* 页面加载时淡入动画 */
            will-change: opacity, transform;
            /* 告诉浏览器优化 opacity 和 transform 动画 */
        }

        /* 淡入动画定义 */
        @keyframes fadeIn {
            from {
                opacity: 0;
                /* 初始透明 */
                transform: translateY(20px);
                /* 向下偏移 */
            }

            to {
                opacity: 1;
                /* 变为不透明 */
                transform: translateY(0);
                /* 回到正常位置 */
            }
        }

        /* 旋转动画定义 */
        @keyframes spin {
            0% {
                transform: rotate(0deg);
                /* 初始角度 */
            }

            100% {
                transform: rotate(360deg);
                /* 结束角度 */
            }
        }

        /* ========== 左侧侧边栏系统 ========== */
        .sidebar {
            width: 320px;
            /* 固定宽度 */
            background: linear-gradient(160deg, #2c3e50, #1a252f);
            /* 深色渐变背景 */
            color: #f0f3f7;
            /* 亮色字体 */
            overflow-y: auto;
            /* 垂直方向出现滚动条 */
            border-right: 1px solid #3a506b;
            /* 右侧边框分割 */
            position: sticky;
            /* 滚动时固定在顶部 */
            top: 20px;
            /* 距离顶部 20px */
            align-self: flex-start;
            /* 自身顶部对齐 */
            border-radius: 12px;
            /* 圆角 */
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            /* 阴影，增加立体感 */
            max-height: calc(100vh - 40px);
            /* 最大高度，防止溢出视口 */
            opacity: 1;
            /* 默认完全不透明 */
            transition: transform 0.3s ease;
            /* 平滑过渡 transform 变化 */
        }

        /* 侧边栏悬停效果 */
        .sidebar:hover {
            transform: translateY(-5px);
            /* 鼠标悬停时稍微向上移动 */
            box-shadow: 0 12px 28px rgba(0, 0, 0, 0.35);
            /* 阴影加深，柔和效果 */
        }

        /* ========== 侧边栏头部样式 ========== */
        .sidebar-header {
            padding: 20px;
            /* 内边距 */
            background: rgba(26, 37, 47, 1);
            /* 纯色背景，和侧边栏区分 */
            text-align: center;
            /* 居中对齐文本 */
            border-bottom: 1px solid #3a506b;
            /* 底部边框 */
            position: sticky;
            /* 固定顶部 */
            top: 0;
            /* 距离顶部 0 */
            z-index: 10;
            /* 保证悬浮层在上方 */
            box-shadow: inset 0 -2px 5px rgba(0, 0, 0, 0.1);
            /* 内阴影，增加层次感 */
        }

        .sidebar-header h2 {
            font-size: 1.8rem;
            /* 标题字体大小 */
            margin-top: 0;
            /* 去除上边距 */
            margin-bottom: 10px;
            /* 底部间距 */
            color: #3498db;
            /* 主题蓝色 */
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            /* 轻微阴影增强立体感 */
        }

        .sidebar-header p {
            font-size: 1.1rem;
            /* 副标题字体大小 */
            margin-bottom: 5px;
            /* 底部间距 */
            color: #bdc3c7;
            /* 浅灰色字体 */
        }

        /* ========== 目录层级结构样式 ========== */
        /* 基础变量定义 */
        :root {
            --base-font-size: 1.15rem;
            /* 基本字体大小 */
            --padding-increment: 20px;
            /* 缩进增量 */
            --opacity-decrement: 0.05;
            /* 透明度减少量 */
            --font-weight-decrement: 100;
            /* 字体粗细减少量 */
            --font-size-decrement: 0.05rem;
            /* 字体大小减少量 */
        }

        /* 一级目录项样式 */
        .level1 {
            font-weight: 700;
            /* 字体粗细为 700，表示加粗 */
            font-size: var(--base-font-size);
            /* 使用基础字体大小 */
            border-bottom: 1px solid #3a506b;
            /* 底部添加 1px 实线边框，颜色为 #3a506b */
            padding-left: calc(var(--padding-increment) * 1 + 15px);
            /* 左侧内边距为 20px * 1 + 15px，共 35px */
            color: #ffffff;
            /* 字体颜色为白色 */
        }

        /* 二级目录项样式 */
        .level2 {
            padding-left: calc(var(--padding-increment) * 2 + 15px);
            /* 左侧内边距为 20px * 2 + 15px，共 55px */
            font-size: calc(var(--base-font-size) - var(--font-size-decrement) * 4);
            /* 字体大小为基础字体大小减去 4 倍的减少量 */
            font-weight: calc(700 - var(--font-weight-decrement) * 2);
            /* 字体粗细为 700 减去 2 倍的减少量，结果为 500 */
            color: #ffffff;
            /* 字体颜色为白色 */
        }

        /* 三级目录项样式 */
        .level3 {
            padding-left: calc(var(--padding-increment) * 3 + 15px);
            /* 左侧内边距为 20px * 3 + 15px，共 75px */
            font-size: calc(var(--base-font-size) - var(--font-size-decrement) * 5);
            /* 字体大小为基础字体大小减去 5 倍的减少量 */
            font-weight: calc(700 - var(--font-weight-decrement) * 3);
            /* 字体粗细为 700 减去 3 倍的减少量，结果为 400 */
            color: #ffffff;
            /* 字体颜色为白色 */
            opacity: calc(1 - var(--opacity-decrement) * 2);
            /* 透明度为 1 减去 2 倍的减少量，结果为 0.9 */
        }

        /* 四级目录项样式 */
        .level4 {
            padding-left: calc(var(--padding-increment) * 4 + 15px);
            /* 左侧内边距为 20px * 4 + 15px，共 95px */
            font-size: calc(var(--base-font-size) - var(--font-size-decrement) * 6);
            /* 字体大小为基础字体大小减去 6 倍的减少量 */
            font-weight: calc(700 - var(--font-weight-decrement) * 4);
            /* 字体粗细为 700 减去 4 倍的减少量，结果为 300 */
            color: #ffffff;
            /* 字体颜色为白色 */
            opacity: calc(1 - var(--opacity-decrement) * 3);
            /* 透明度为 1 减去 3 倍的减少量，结果为 0.85 */
        }

        /* 五级目录项样式 */
        .level5 {
            padding-left: calc(var(--padding-increment) * 5 + 15px);
            /* 左侧内边距为 20px * 5 + 15px，共 115px */
            font-size: calc(var(--base-font-size) - var(--font-size-decrement) * 7);
            /* 字体大小为基础字体大小减去 7 倍的减少量 */
            font-weight: calc(700 - var(--font-weight-decrement) * 5);
            /* 字体粗细为 700 减去 5 倍的减少量，结果为 300 */
            color: #ffffff;
            /* 字体颜色为白色 */
            opacity: calc(1 - var(--opacity-decrement) * 4);
            /* 透明度为 1 减去 4 倍的减少量，结果为 0.80 */
        }

        /* ========== 目录导航系统样式 ========== */
        .directory {
            padding: 0 0;
            /* 移除目录外部间距 */
        }

        /* 目录项基础样式 */
        .directory-item {
            padding: 12px 0;
            /* 目录项上下内边距 */
            cursor: pointer;
            /* 鼠标悬停时显示为手型 */
            transition: all 0.2s;
            /* 平滑过渡效果 */
            position: relative;
            /* 设定相对定位 */
            display: flex;
            /* 使用 flex 布局 */
            align-items: center;
            /* 居中对齐目录项中的内容 */
            border-left: 3px solid transparent;
            /* 设置左侧边框为透明，防止布局变化 */
            min-height: 44px;
            /* 设置目录项的最小高度 */
            box-sizing: border-box;
            /* 包括内边距和边框在内的总宽高计算 */
            font-weight: inherit;
            /* 继承字体粗细 */
        }

        /* 目录项悬停效果 */
        .directory-item:hover {
            background: rgba(52, 73, 94, 0.8);
            /* 悬停时背景颜色变化，透明度 80% */
        }

        /* 活动目录项样式 */
        .directory-item.active {
            background: rgba(41, 128, 185, 0.5);
            /* 激活状态背景色半透明 */
            border-left: 3px solid #3498db;
            /* 激活状态左侧边框为蓝色 */
        }

        /* 目录图标样式 */
        .toggle-icon {
            margin-left: 15px;
            /* 左侧外边距 */
            margin-right: 12px;
            /* 右侧外边距 */
            transition: transform 0.3s ease;
            /* 图标的平滑过渡动画 */
            width: 20px;
            /* 图标宽度 */
            text-align: center;
            /* 图标居中对齐 */
            font-size: 0.9rem;
            /* 设置图标字体大小 */
            flex-shrink: 0;
            /* 不允许图标缩小 */
        }

        /* 子容器样式 */
        .children {
            overflow: hidden;
            /* 隐藏超出部分 */
            transition: max-height 0.4s ease, opacity 0.3s ease;
            /* 平滑过渡效果 */
            opacity: 1;
            /* 初始透明度为 100% */
        }

        /* 折叠状态 */
        .children.collapsed {
            max-height: 0 !important;
            /* 设置最大高度为 0，折叠时内容不可见 */
            opacity: 0;
            /* 设置透明度为 0，折叠时内容完全消失 */
            overflow: hidden;
            /* 隐藏超出部分 */
        }

        /* 展开状态 */
        .children.expanded {
            max-height: 2000px;
            /* 设置最大高度，确保展开时内容可见 */
            opacity: 1;
            /* 设置透明度为 1，展开时内容完全显示 */
            overflow: visible;
            /* 允许内容超出容器显示 */
        }

        /* ========== 侧边栏联系信息区域样式 ========== */
        .contact-sidebar {
            background: rgba(52, 73, 94, 0.8);
            /* 半透明深蓝色背景 */
            border-radius: 8px;
            /* 圆角边框 */
            padding: 15px;
            /* 内边距 */
            margin: 25px 15px 15px 15px;
            /* 外边距 */
            font-size: 14px;
            /* 字体大小 */
            border: 1px solid #3a506b;
            /* 边框样式 */
            color: #fff;
            /* 文字颜色 */
        }

        /* 侧边栏段落样式 */
        .contact-sidebar p {
            margin: 10px 0;
            /* 上下边距 */
            display: flex;
            /* 弹性布局 */
            align-items: center;
            /* 垂直居中 */
            padding-left: 10px;
            /* 左内边距 */
        }

        /* 侧边栏图标样式 */
        .contact-sidebar i {
            margin-right: 12px;
            /* 右外边距 */
            width: 20px;
            /* 固定宽度 */
            text-align: center;
            /* 文本居中 */
            color: #3498db;
            /* 图标颜色 */
        }

        /* 侧边栏文本样式 */
        .contact-sidebar span {
            flex: 1;
            /* 弹性填充剩余空间 */
            color: #fff;
            /* 文字颜色 */
        }

        /* ========== 右侧主内容区域样式 ========== */
        .content {
            flex: 1;
            /* 弹性填充剩余空间 */
            background: rgba(255, 255, 255, 0.97);
            /* 半透明白色背景 */
            padding: 40px;
            /* 内边距 */
            border-radius: 12px;
            /* 圆角边框 */
            box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
            /* 阴影效果 */
            margin-top: 0;
            /* 上外边距 */
            animation: slideIn 0.5s ease-out;
            /* 滑动进入动画 */
        }

        /* 滑动进入动画定义 */
        @keyframes slideIn {
            from {
                transform: translateX(30px);
                /* 初始位置：向右偏移 30px */
                opacity: 0;
                /* 初始透明度 */
            }

            to {
                transform: translateX(0);
                /* 结束位置：恢复正常位置 */
                opacity: 1;
                /* 完全不透明 */
            }
        }

        /* ========== 页面头部区域样式 ========== */
        header {
            text-align: center;
            /* 文本居中 */
            padding: 20px 0 20px;
            /* 内边距 */
        }

        /* 主标题样式 */
        h1 {
            font-size: 36px;
            /* 字体大小 */
            margin-bottom: 10px;
            /* 下外边距 */
            font-weight: 600;
            /* 字体粗细 */
            letter-spacing: 1px;
            /* 字符间距 */
            color: #2c5282;
            /* 文字颜色 */
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            /* 文字阴影 */
            background: linear-gradient(to right, #2c5282, #3498db);
            /* 渐变背景 */
            -webkit-background-clip: text;
            /* 背景裁剪到文字 */
            -webkit-text-fill-color: transparent;
            /* 文字填充透明 */
            padding-bottom: 15px;
            /* 下内边距 */
            border-bottom: 2px solid #e0e6ed;
            /* 底部边框 */
        }

        /* 副标题样式 */
        .subtitle {
            font-size: 20px;
            /* 字体大小 */
            color: #5a6c7d;
            /* 文字颜色 */
            max-width: 700px;
            /* 最大宽度 */
            margin: 0 auto;
            /* 水平居中 */
            margin-top: 15px;
            /* 上外边距 */
        }

        /* ========== 标题层级体系样式 ========== */
        h2 {
            color: #2c5282;
            /* 文字颜色 */
            padding: 25px 0 15px;
            /* 内边距 */
            margin-top: 20px;
            /* 上外边距 */
            border-bottom: 2px solid #d1e5f0;
            /* 底部边框 */
            font-size: 28px;
            /* 字体大小 */
            position: relative;
            /* 相对定位 */
        }

        /* h2 标题前的装饰线 */
        h2::before {
            content: "";
            /* 伪元素内容 */
            position: absolute;
            /* 绝对定位 */
            bottom: -2px;
            /* 底部位置 */
            left: 0;
            /* 左侧对齐 */
            width: 120px;
            /* 宽度 */
            height: 4px;
            /* 高度 */
            background: linear-gradient(to right, #3498db, #2ecc71);
            /* 渐变背景 */
            border-radius: 2px;
            /* 圆角 */
        }

        /* 三级标题样式 */
        h3 {
            color: #3a6ea5;
            /* 文字颜色 */
            padding: 20px 0 12px;
            /* 内边距 */
            font-size: 24px;
            /* 字体大小 */
            margin-top: 25px;
            /* 上外边距 */
        }

        /* 四级标题样式 */
        h4 {
            color: #4a86c7;
            /* 文字颜色 */
            padding: 15px 0 10px;
            /* 内边距 */
            font-size: 20px;
            /* 字体大小 */
            margin-top: 15px;
            /* 上外边距 */
        }

        /* 五级标题样式 */
        h5 {
            color: #5a96d7;
            /* 文字颜色 */
            padding: 12px 0 8px;
            /* 内边距 */
            font-size: 18px;
            /* 字体大小 */
            margin-top: 12px;
            /* 上外边距 */
        }

        /* ========== 文本段落样式 ========== */
        p {
            margin: 15px 0;
            /* 上下外边距 */
            color: #444;
            /* 文字颜色 */
            line-height: 1.7;
            /* 行高 */
        }

        /* ========== 表格展示系统 (增强版) ========== */
        .table-container {
            background: #f8fafd;
            /* 背景色 */
            padding: 20px;
            /* 内边距 */
            border-radius: 10px;
            /* 圆角 */
            margin: 20px 0 30px;
            /* 外边距 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            /* 阴影 */
            border: 1px solid #e0e6ed;
            /* 边框 */
            overflow-x: auto;
            /* 水平滚动 */
            overflow-y: auto;
            /* 垂直滚动 */
            transition: all 0.3s ease;
            /* 过渡效果 */
            max-width: 100%;
            /* 最大宽度 */
            position: relative;
            /* 相对定位 */
            max-width: none;
            /* 覆盖最大宽度 */
        }

        /* 表格容器悬停效果 */
        .table-container:hover {
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
            /* 阴影增强 */
        }

        /* 超宽表格的特殊处理 */
        .table-container.wide-table {
            overflow-x: scroll;
            /* 强制水平滚动 */
            -webkit-overflow-scrolling: touch;
            /* iOS 平滑滚动 */
        }

        /* 基本表格样式 */
        table {
            width: 100%;
            /* 宽度 100% */
            border-collapse: separate;
            /* 边框分离 */
            border-spacing: 0;
            /* 边框间距 */
            font-size: 15px;
            /* 字体大小 */
            border-radius: 8px;
            /* 圆角 */
            overflow: hidden;
            /* 隐藏溢出 */
            min-width: 600px;
            /* 最小宽度 */
            table-layout: auto;
            /* 表格布局自动 */
        }

        /* 内容丰富的表格样式 */
        .table-container table.content-table {
            min-width: 800px;
            /* 更大的最小宽度 */
        }

        /* 表头和单元格基本样式 */
        th,
        td {
            border: 1px solid #d1e5f0;
            /* 边框 */
            padding: 14px 18px;
            /* 内边距 */
            text-align: left;
            /* 文本左对齐 */
            vertical-align: top;
            /* 垂直顶部对齐 */
            word-wrap: break-word;
            /* 单词换行 */
            max-width: 400px;
            /* 最大宽度 */
            vertical-align: middle;
            /* 垂直居中 */
        }

        /* 表头特殊样式 */
        th {
            background: linear-gradient(to bottom, #4a86c7, #3a6ea5);
            /* 渐变背景 */
            color: white;
            /* 文字颜色 */
            font-weight: 600;
            /* 字体粗细 */
            text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
            /* 文字阴影 */
            font-size: 16px;
            /* 字体大小 */
            position: sticky;
            /* 粘性定位 */
            top: 0;
            /* 顶部固定 */
            z-index: 10;
            /* 层级 */
            text-align: center;
            /* 文本居中 */
        }

        /* 第一行第一列表头样式 */
        tr:first-child th:first-child {
            width: 22%;
            /* 宽度 */
            text-align: center;
            /* 文本居中 */
        }

        /* 第一列单元格样式 */
        td:first-child {
            width: 22%;
            /* 宽度 */
            font-weight: 600;
            /* 字体粗细 */
            color: #2c5282;
            /* 文字颜色 */
            background-color: #f0f7ff;
            /* 背景色 */
            text-align: center;
            /* 文本居中 */
        }

        /* 偶数行背景色 */
        tr:nth-child(even) {
            background-color: #f8fafd;
            /* 浅色背景 */
        }

        /* 行悬停效果 */
        tr:hover {
            background-color: #e8f4ff;
            /* 背景色变化 */
            transition: background 0.3s;
            /* 过渡效果 */
        }

        /* ========== 内容区块组件样式 ========== */
        .section {
            margin-bottom: 10px;
            /* 下外边距 */
            padding-bottom: 0px;
            /* 下内边距 */
            border-left: 3px solid transparent;
            /* 透明左边框 */
            padding-left: 10px;
            /* 左内边距 */
            transition: all 0.3s;
            /* 过渡效果（文档1 缺失，从文档2 补充） */
        }

        /* 区块悬停效果 */
        .section:hover {
            border-left: 3px solid #3498db;
            /* 左边框颜色变化 */
        }

        /* 提示框样式 */
        .note {
            background: #e3f2fd;
            /* 背景色 */
            border-left: 4px solid #3498db;
            /* 左边框 */
            padding: 18px;
            /* 内边距 */
            margin: 20px 0;
            /* 外边距 */
            border-radius: 0 8px 8px 0;
            /* 圆角 */
            box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05);
            /* 阴影 */
        }

        /* 重要提示框样式 */
        .important {
            background: #fff8e6;
            /* 背景色 */
            border-left: 4px solid #ffc107;
            /* 左边框 */
            padding: 18px;
            /* 内边距 */
            margin: 20px 0;
            /* 外边距 */
            border-radius: 0 8px 8px 0;
            /* 圆角 */
            font-weight: 500;
            /* 字体粗细 */
            box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05);
            /* 阴影 */
        }

        /* ========== 联系信息展示区域样式 ========== */
        .contact-info {
            background: linear-gradient(to right, #e3f2fd, #f0f7ff);
            /* 渐变背景 */
            padding: 25px;
            /* 内边距 */
            border-radius: 10px;
            /* 圆角 */
            margin-top: 35px;
            /* 上外边距 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            /* 阴影 */
            border: 1px solid #d1e5f0;
            /* 边框 */
        }

        /* 联系信息网格布局 */
        .contact-grid {
            display: grid;
            /* 网格布局 */
            grid-template-columns: repeat(2, 1fr);
            /* 两列等宽 */
            gap: 18px;
            /* 间距 */
        }

        /* 联系信息项样式 */
        .contact-item {
            display: flex;
            /* 弹性布局 */
            align-items: center;
            /* 垂直居中 */
            background: rgba(255, 255, 255, 0.7);
            /* 半透明白色背景 */
            padding: 12px 15px;
            /* 内边距 */
            border-radius: 8px;
            /* 圆角 */
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
            /* 阴影 */
            transition: transform 0.3s;
            /* 过渡效果 */
        }

        /* 联系信息项悬停效果 */
        .contact-item:hover {
            transform: translateY(-3px);
            /* 上移效果 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            /* 阴影增强 */
        }

        /* 联系信息标签样式 */
        .contact-label {
            font-weight: 600;
            /* 字体粗细 */
            min-width: 100px;
            /* 最小宽度 */
            color: #2c5282;
            /* 文字颜色 */
        }

        /* 联系信息值样式 */
        .contact-value {
            flex: 1;
            /* 弹性填充 */
            padding: 5px;
            /* 内边距 */
            border: 1px solid transparent;
            /* 透明边框 */
            border-radius: 4px;
            /* 圆角 */
            transition: all 0.3s;
            /* 过渡效果（文档1 缺失，从文档2 补充） */
        }

        /* 联系信息值聚焦效果 */
        .contact-value:focus {
            border-color: #3498db;
            /* 边框颜色 */
            background-color: #fff;
            /* 背景色 */
            outline: none;
            /* 去除轮廓 */
            box-shadow: 0 0 5px rgba(52, 152, 219, 0.5);
            /* 阴影 */
        }

        /* ========== 页面底部页脚样式 ========== */
        .footer {
            text-align: center;
            /* 文本居中对齐 */
            padding: 25px;
            /* 内边距25px */
            color: #7f8c8d;
            /* 文字颜色为浅灰色 */
            font-size: 15px;
            /* 字体大小15px */
            background: linear-gradient(to right, #f0f7ff, #e3f2fd);
            /* 浅蓝色渐变背景 */
            border-top: 1px solid #d1e5f0;
            /* 顶部1px浅蓝色边框 */
            margin-top: 20px;
            /* 上外边距20px */
            border-radius: 0 0 12px 12px;
            /* 底部左右圆角12px */
            box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
            /* 顶部轻微阴影（文档2补充） */
        }

        /* 页脚段落样式 */
        .footer p {
            margin: 0;
            /* 清除默认外边距 */
            color: #5a6c7d;
            /* 文字颜色为深灰色 */
            line-height: 1.5;
            /* 行高1.5倍（文档2补充） */
        }

        /* 页脚链接样式 */
        .footer a {
            color: #3498db;
            /* 链接颜色为主题蓝色 */
            text-decoration: none;
            /* 去除下划线 */
            transition: color 0.3s;
            /* 颜色过渡效果（文档2补充） */
        }

        .footer a:hover {
            color: #2c5282;
            /* 悬停时颜色加深 */
            text-decoration: underline;
            /* 悬停时显示下划线（文档2补充） */
        }

        /* 响应式调整（文档2补充） */
        @media (max-width: 768px) {
            .footer {
                padding: 20px 15px;
                /* 移动端减小内边距 */
                font-size: 14px;
                /* 字体略缩小 */
            }
        }

        /* ========== 可编辑单元格功能样式 ========== */
        .editable-cell {
            display: block;
            /* 块级元素 */
            width: 100%;
            /* 宽度100% */
            min-height: 24px;
            /* 最小高度 */
            padding: 5px;
            /* 内边距 */
            background: transparent;
            /* 透明背景 */
            border: 1px solid transparent;
            /* 透明边框 */
            border-radius: 4px;
            /* 圆角 */
            transition: all 0.3s;
            /* 过渡效果 */
            cursor: text;
            /* 文本指针 */
            outline: none;
            /* 去除轮廓 */
            color: inherit;
            /* 继承文字颜色 */
            white-space: pre-wrap;
            /* 保留空白和换行（文档1缺失，从文档2补充） */
        }

        /* 可编辑单元格悬停和聚焦效果 */
        .editable-cell:hover,
        .editable-cell:focus {
            border: 1px solid #3498db;
            /* 边框颜色 */
            background-color: #fff;
            /* 背景色 */
            box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
            /* 阴影 */
        }

        /* ========== 占位符提示系统样式 ========== */
        .editable-cell:empty:before {
            content: attr(placeholder);
            /* 显示placeholder属性 */
            color: #aaa;
            /* 浅灰色文字 */
        }

        /* 自动数据样式 */
        .auto-data {
            color: #2c5282;
            /* 文字颜色 */
            font-weight: 500;
            /* 字体粗细 */
        }

        /* ========== 数据操作控制按钮样式 ========== */
        .data-controls {
            display: flex;
            /* 弹性布局 */
            gap: 15px;
            /* 间距 */
            margin-top: 20px;
            /* 上外边距 */
            margin-bottom: 10px;
            /* 下外边距 */
            justify-content: center;
            /* 水平居中 */
        }

        /* 数据按钮基础样式 */
        .data-btn {
            padding: 12px 25px;
            /* 内边距 */
            background: linear-gradient(to right, #3498db, #2c5282);
            /* 渐变背景 */
            color: white;
            /* 文字颜色 */
            border: none;
            /* 无边框 */
            border-radius: 5px;
            /* 圆角 */
            cursor: pointer;
            /* 指针样式 */
            font-weight: 600;
            /* 字体粗细 */
            transition: all 0.3s;
            /* 过渡效果 */
            box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
            /* 阴影 */
            display: flex;
            /* 弹性布局 */
            align-items: center;
            /* 垂直居中 */
            gap: 8px;
            /* 间距 */
        }

        /* 数据按钮悬停效果 */
        .data-btn:hover {
            transform: translateY(-3px);
            /* 上移效果 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
            /* 阴影增强 */
        }

        /* 重置按钮特殊样式 */
        .data-btn.reset {
            background: linear-gradient(to right, #e74c3c, #c0392b);
            /* 红色渐变 */
        }

        /* 保存按钮特殊样式 */
        .data-btn.save {
            background: linear-gradient(to right, #2ecc71, #27ae60);
            /* 绿色渐变 */
        }

        /* 导出按钮特殊样式 */
        .data-btn.export {
            background: linear-gradient(to right, #f39c12, #e67e22);
            /* 橙色渐变 */
        }

        /* ========== 状态提示栏系统样式 ========== */
        .status-bar {
            text-align: center;
            /* 文本居中 */
            padding: 12px;
            /* 内边距 */
            margin-top: 15px;
            /* 上外边距 */
            margin-bottom: 15px;
            /* 下外边距 */
            border-radius: 5px;
            /* 圆角 */
            background: #e3f2fd;
            /* 背景色 */
            color: #2c5282;
            /* 文字颜色 */
            font-weight: 500;
            /* 字体粗细 */
            display: none;
            /* 默认隐藏 */
        }

        /* ========== 系统信息表格特殊样式 ========== */
        .sysinfo-table .auto-data {
            white-space: pre-wrap;
            /* 保留空白和换行 */
            font-family: 'Consolas', 'Courier New', monospace;
            /* 等宽字体 */
            font-size: 14px;
            /* 字体大小 */
            line-height: 1.4;
            /* 行高 */
            padding: 8px;
            /* 内边距 */
            background-color: #f8fafd;
            /* 背景色 */
            border-radius: 4px;
            /* 圆角 */
            border: 1px solid #e0e6ed;
            /* 边框（文档1缺失，从文档2补充） */
        }

        /* ========== 回到顶部功能按钮样式 ========== */
        .back-to-top {
            position: fixed;
            /* 固定定位 */
            bottom: 60px;
            /* 底部距离 */
            right: 85px;
            /* 右侧距离 */
            background: linear-gradient(to right, #3498db, #2c5282);
            /* 渐变背景 */
            color: white;
            /* 文字颜色 */
            width: 50px;
            /* 宽度 */
            height: 50px;
            /* 高度 */
            border-radius: 50%;
            /* 圆形 */
            display: flex;
            /* 弹性布局 */
            align-items: center;
            /* 垂直居中 */
            justify-content: center;
            /* 水平居中 */
            cursor: pointer;
            /* 指针样式 */
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
            /* 阴影 */
            z-index: 100;
            /* 层级 */
            opacity: 0.8;
            /* 透明度 */
            transition: all 0.3s;
            /* 过渡效果（文档1缺失，从文档2补充） */
        }

        /* 返回顶部按钮悬停效果 */
        .back-to-top:hover {
            opacity: 1;
            /* 不透明 */
            transform: translateY(-5px);
            /* 上移效果 */
        }

        /* ========== 滚动条样式优化 ========== */
        .sidebar::-webkit-scrollbar {
            width: 8px;
            /* 滚动条宽度 */
        }

        .sidebar::-webkit-scrollbar-thumb {
            background-color: rgba(52, 152, 219, 0.6);
            /* 滚动条滑块颜色 */
            border-radius: 4px;
            /* 滑块圆角 */
        }

        .sidebar::-webkit-scrollbar-track {
            background: transparent;
            /* 滚动条轨道透明 */
        }

        .table-container::-webkit-scrollbar {
            height: 8px;
            /* 高度 */
            width: 8px;
            /* 宽度 */
        }

        .table-container::-webkit-scrollbar-track {
            background: #f1f1f1;
            /* 轨道背景 */
            border-radius: 4px;
            /* 圆角 */
        }

        .table-container::-webkit-scrollbar-thumb {
            background: #c1c1c1;
            /* 滑块颜色 */
            border-radius: 4px;
            /* 圆角 */
        }

        .table-container::-webkit-scrollbar-thumb:hover {
            background: #a8a8a8;
            /* 滑块悬停颜色 */
        }

        /* ========== 加载指示器样式 ========== */
        .loading-container {
            position: fixed;
            /* 固定定位 */
            top: 0;
            /* 顶部对齐 */
            left: 0;
            /* 左侧对齐 */
            width: 100%;
            /* 宽度100% */
            height: 100%;
            /* 高度100% */
            background: rgba(0, 0, 0, 0.8);
            /* 半透明黑色背景 */
            display: flex;
            /* 弹性布局 */
            justify-content: center;
            /* 水平居中 */
            align-items: center;
            /* 垂直居中 */
            z-index: 1000;
            /* 高层级 */
            flex-direction: column;
            /* 垂直排列 */
        }

        /* 加载动画样式 */
        .loader {
            width: 80px;
            /* 宽度 */
            height: 80px;
            /* 高度 */
            border: 10px solid rgba(255, 255, 255, 0.1);
            /* 边框 */
            border-radius: 50%;
            /* 圆形 */
            border-top: 10px solid #3498db;
            /* 顶部边框颜色 */
            animation: spin 1s linear infinite;
            /* 旋转动画 */
        }

        /* 加载文字样式 */
        .loading-container div:last-child {
            color: white;
            /* 文字颜色 */
            margin-top: 20px;
            /* 上外边距 */
            font-size: 18px;
            /* 字体大小 */
        }

        /* ========== 响应式设计 ========== */
        @media (max-width: 1200px) {
            .container {
                flex-direction: column;
                /* 垂直布局 */
            }

            .sidebar {
                position: relative;
                /* 相对定位 */
                top: 0;
                /* 取消偏移 */
                width: 100%;
                /* 宽度自适应 */
                max-height: none;
                /* 高度不限制 */
                margin-bottom: 30px;
                /* 底部间距 */
            }
        }

        /* 中等屏幕尺寸响应式 */
        @media (max-width: 768px) {
            .content {
                padding: 20px 15px;
                /* 调整内边距 */
            }

            .contact-grid {
                grid-template-columns: 1fr;
                /* 单列布局 */
            }

            h1 {
                font-size: 28px;
                /* 缩小标题字体 */
            }

            h2 {
                font-size: 24px;
                /* 缩小副标题字体 */
            }

            h3 {
                font-size: 22px;
                /* 缩小三级标题字体 */
            }

            table {
                font-size: 14px;
                /* 缩小表格字体 */
                min-width: 500px;
                /* 调整最小宽度 */
            }

            th,
            td {
                padding: 10px 12px;
                /* 减小单元格内边距 */
            }

            .data-controls {
                flex-direction: column;
                /* 垂直排列按钮 */
            }

            .sidebar-header h2 {
                font-size: 1.5rem;
                /* 缩小侧边栏标题 */
            }

            /* 移动端表格优化 */
            .table-container {
                padding: 10px;
                /* 减小内边距 */
            }
        }
    </style>
</head>

<body>
    <!-- 加载指示器 -->
    <div class="loading-container" id="loading">
        <div class="loader"></div>
        <div>正在加载数据库配置...</div>
    </div>

    <!-- 主容器 -->
    <div class="container">
        <!-- 左侧侧边栏 -->
        <div class="sidebar">
            <div class="sidebar-header">
                <h2>数据库部署报告</h2>
                <p>目录导航</p>
            </div>
            <!-- 目录导航区域 -->
            <div class="directory" id="directory"></div>
            <!-- 联系信息侧边栏 -->
            <div class="contact-sidebar"></div>
        </div>

        <!-- 右侧主内容区域 -->
        <div class="content">
            <!-- 页面头部 -->
            <header>
                <h1>数据库部署报告</h1>
                <p class="subtitle">达梦数据库部署与配置文档 | 全栈数据产品&解决方案提供商</p>
            </header>

            <!-- 项目信息部分 -->
            <div class="section" id="section1"></div>

            <!-- 节点信息容器 -->
            <div id="nodes-container"></div>

            <!-- 运维操作容器 -->
            <div id="operations-container"></div>

            <!-- 技术支持容器 -->
            <div id="support-container"></div>

            <!-- 数据操作按钮 -->
            <div class="data-controls">
                <button class="data-btn save" onclick="saveAllData()">
                    <i class="fas fa-save"></i> 保存数据
                </button>
                <button class="data-btn export" onclick="exportToHTML()">
                    <i class="fas fa-download"></i> 导出HTML
                </button>
                <button class="data-btn reset" onclick="resetAllData()">
                    <i class="fas fa-undo"></i> 重置数据
                </button>
            </div>

            <!-- 状态提示栏 -->
            <div class="status-bar" id="statusBar">数据已成功保存！</div>

            <!-- 页脚 -->
            <div class="footer">
                <p>© 2025 达梦数据库 | 数据库部署报告 | 版本 1.5.0</p>
            </div>
        </div>
    </div>

    <!-- 回到顶部按钮 -->
    <div class="back-to-top" onclick="scrollToTop()">↑</div>


    <script>
        // 1. 配置抽取与管理模块
        const AppConfig = {
            // DOM选择器缓存
            selectors: {
                directory: '#directory',
                content: '.content',
                sidebar: '.sidebar',
                loading: '#loading',
                statusBar: '#statusBar',
                nodesContainer: '#nodes-container',
                operationsContainer: '#operations-container',
                supportContainer: '#support-container'
            },

            // 操作键映射配置 - 确保与projectData键名完全匹配
            operationKeyMap: {
                // common字段映射
                'userName': '用户名称',
                'projectName': '项目名称',
                'developer': '开发商',
                'businessSystem': '业务系统',
                'deployDate': '部署日期',
                'dmInstallMode': '安装模式',

                // host字段映射
                'hostIp': '主机IP',
                'hostUsername': '用户名',
                'hostPassword': '密码',

                // database字段映射
                'dbIp': '数据库IP',
                'dbPort': '端口',
                'sysdbaPassword': 'SYSDBA密码',
                'sysauditorPassword': 'SYSAUDITOR密码',
                'sysssoPassword': 'SYSSSO密码',

                // serverInfo字段映射
                'serverIp': 'IP地址',
                'osVersion': '操作系统',
                'kernelVersion': '内核版本',
                'hostname': '主机名',

                // license字段映射
                'licenseVersion': '许可证版本',
                'licenseSeriesNo': '序列号',
                'licenseServerSeries': '校验码',
                'licenseServerType': '产品类型',
                'licenseProjectName': '项目名称',
                'licenseExpire': '有效日期',
                'licenseAuthorizedCustomer': '最终用户',
                'licenseAuthorizedUserNumber': '授权用户数',
                'licenseConcurrencyUserNumber': '授权并发数',
                'licenseCpuCount': '授权CPU个数',
                'licenseCpuCores': '授权CPU核数',
                'licenseClusterType': '授权集群',

                // databaseInstance字段映射
                'dbVersion': '版本号',
                'dbBuildVersion': '编译版本号',
                'dbName': '数据库名',
                'dbInstance': '实例名',
                'dbExtentSize': '簇大小',
                'dbPageSize': '页大小',
                'dbCaseSensitive': '大小写敏感',
                'dbCharset': '字符集',
                'dbCharUnit': '字符单位',
                'dbBlankPadding': '空格填充模式',
                'dbCompatibility': '兼容性参数',
                'dbLogCount': '日志文件个数',
                'dbLogSize': '日志文件大小',
                'dbArchiveEnabled': '归档启用',
                'dbCreateTime': '创建时间',
                'dbStartupTime': '启动时间',

                // directories字段映射
                'installDir': '安装目录',
                'instanceDir': '实例目录',
                'archiveDir': '归档目录',
                'backupDir': '备份目录',

                // configFiles字段映射
                'dmIni': 'dm.ini',
                'dmmalIni': 'dmmal.ini',
                'dmarchIni': 'dmarch.ini',
                'dmwatcherIni': 'dmwatcher.ini',
                'dmmonitorIni': 'dmmonitor.ini',
                'sqllogIni': 'sqllog.ini',

                // operations字段映射
                'standaloneStop': '停止数据库',
                'standaloneStart': '启动数据库',
                'standaloneManager': '管理工具',
                'standaloneDisql': '命令行工具',
                'datawatchStop': '停止集群',
                'datawatchStart': '启动集群',
                'datawatchManager': '管理工具',
                'datawatchDisql': '命令行工具',
                'datawatchNote': '注意事项',
                'raftStop': '停止集群',
                'raftStart': '启动集群',
                'raftManager': '管理工具',
                'raftDisql': '命令行工具',
                'raftNote': '注意事项',
                'dscStop': '停止集群',
                'dscStart': '启动集群',
                'dscManager': '管理工具',
                'dscDisql': '命令行工具',
                'dscNote': '注意事项',

                // support字段映射
                'author': '作者',
                'mobile': '手机',
                'email': '邮箱',
                'wechat': '微信',
                'manual': '官方手册',
                'website': '官方网站',
                'eco': '云适配中心',

                // 运维命令映射
                'createTablespace': '创建表空间',
                'createUser': '创建用户',
                'grantPrivileges': '授权',
                'resizeLogfile': '扩大联机日志文件',
                'viewLicense': '查看授权信息',
                'replaceLicense': '更换授权文件步骤',
                'initJobEnv': '打开代理环境',
                'fullBackupJob': '全量备份作业',
                'incrementalBackupJob': '增量备份作业',
                'viewInstanceStatus': '查看实例状态',
                'viewWatcherStatus': '查看守护进程状态',
                'normalSwitchover': '正常切换',
                'primaryFailover': '主库故障切换',

                // 高可用配置映射
                'dmSvcConf': 'dm_svc.conf配置',
                'appConnConf': '应用连接串配置',
                'dmSvcConfRW': 'dm_svc.conf配置（读写分离）',
                'appConnConfRW': '应用连接串配置（读写分离）'
            },

            // 样式类名配置
            cssClasses: {
                editableCell: 'editable-cell',
                contactValue: 'contact-value',
                directoryItem: 'directory-item',
                children: 'children',
                collapsed: 'collapsed',
                expanded: 'expanded',
                active: 'active',
                autoData: 'auto-data'
            },

            // 性能配置
            performance: {
                saveDebounceDelay: 2000,
                scrollThrottleDelay: 100,
                batchUpdateSize: 10
            },

            // 高可用和读写分离配置
            haConfig: {
                // 通用文件位置说明
                fileLocationInfo: `
                    <p>配置dm_svc.conf 文件，文件存放位置如下：</p>
                    <ul>
                        <li>Linux：将dm_svc.conf文件放在应用服务器/etc目录下。</li>
                        <li>Windows32位：将dm_svc.conf文件放在应用服务器system32目录下。</li>
                        <li>Windows64位：将dm_svc.conf文件放在应用服务器system32或syswow64目录下。</li>
                    </ul>
                `,
                // 应用连接串模板
                connectionTemplate: `//定义 DM JDBC 驱动串
String jdbcString = "dm.jdbc.driver.DmDriver";
//定义 DM URL 连接串
String urlString = "jdbc:dm://DM";
//定义 DM 用户连接串
String userString = "SYSDBA";
//定义 DM 密码连接串
String pwdString = "{{sysdbaPassword}}";`,
                // 连接说明
                connectionInfo: `说明：用户使用 DM 的 JDBC、DPI 等接口连接服务器时，如使用配置的连接服务名进行连接，客户端会随机选择一台配置项中 ip 代表的服务器进行连接。
如果连接不成功或者服务器状态不正确，客户端将顺序获取下一台（将配置的所有 ip 视为一个环）服务器进行连接，直至连接成功或者全部失败。`
            },

            // 安装模式配置
            installModes: ['single', 'datawatch', 'raft', 'dsc', 'dscm']
        };

        /**
         * @module DOMUtils
         * @description 一个用于优化DOM操作的模块，提供元素缓存、批量更新和性能工具（节流、防抖）。
         */
        const DOMUtils = (() => {
            // DOM缓存
            const cache = new Map();
            /**
             * 获取并缓存单个DOM元素。
             * @param {string} selector - CSS选择器。
             * @returns {Element|null} 查找到的DOM元素，如果未找到则返回null。
             */
            function getElement(selector) {
                if (!cache.has(selector)) {
                    cache.set(selector, document.querySelector(selector));
                }
                return cache.get(selector);
            }
            /**
             * 获取并缓存DOM元素列表。
             * @param {string} selector - CSS选择器。
             * @returns {NodeListOf<Element>} 查找到的DOM元素节点列表。
             */
            function getElements(selector) {
                const cacheKey = `all_${selector}`;
                if (!cache.has(cacheKey)) {
                    cache.set(cacheKey, document.querySelectorAll(selector));
                }
                return cache.get(cacheKey);
            }
            /**
             * 清空内部的DOM元素缓存。
             * @returns {void}
             */
            function clearCache() {
                cache.clear();
            }
            /**
             * 创建一个文档片段（DocumentFragment），用于高效的批量DOM操作。
             * @returns {DocumentFragment} 一个新的文档片段。
             */
            function createFragment() {
                return document.createDocumentFragment();
            }
            /**
             * 批量更新DOM，通过文档片段减少重绘和回流。
             * @param {Array<Function>} updates - 一个包含更新操作的函数数组。
             * @returns {DocumentFragment} 包含所有更新内容的文档片段。
             */
            function batchUpdate(updates) {
                const fragment = createFragment();
                updates.forEach(update => {
                    if (typeof update === 'function') {
                        update(fragment);
                    }
                });
                return fragment;
            }
            /**
             * 创建一个节流函数，在指定时间间隔内最多执行一次。
             * @param {Function} func - 需要节流的函数。
             * @param {number} delay - 时间间隔（毫秒）。
             * @returns {Function} 返回一个新的节流函数。
             */
            function throttle(func, delay) {
                let timeoutId;
                let lastExecTime = 0;
                return function (...args) {
                    const currentTime = Date.now();
                    if (currentTime - lastExecTime > delay) {
                        func.apply(this, args);
                        lastExecTime = currentTime;
                    } else {
                        clearTimeout(timeoutId);
                        timeoutId = setTimeout(() => {
                            func.apply(this, args);
                            lastExecTime = Date.now();
                        }, delay - (currentTime - lastExecTime));
                    }
                };
            }
            /**
             * 创建一个防抖函数，在事件触发后延迟指定时间执行，如果期间再次触发则重新计时。
             * @param {Function} func - 需要防抖的函数。
             * @param {number} delay - 延迟时间（毫秒）。
             * @returns {Function} 返回一个新的防抖函数。
             */
            function debounce(func, delay) {
                let timeoutId;
                return function (...args) {
                    clearTimeout(timeoutId);
                    timeoutId = setTimeout(() => func.apply(this, args), delay);
                };
            }
            return {
                getElement,
                getElements,
                clearCache,
                createFragment,
                batchUpdate,
                throttle,
                debounce
            };
        })();

        /**
         * @module HTMLGenerator
         * @description 一个用于生成HTML片段的模块，封装了各种HTML结构的创建逻辑。
         */
        const HTMLGenerator = (() => {
            // 重置用于自动生成序号的全局计数器
            function resetSectionCounters() {
                window.sectionCounters = {};
            }
            /**
             * 生成完整表格的模板函数
             * @param {object} data - 表格数据对象（键值对）
             * @param {object} options - 配置选项
             * @param {string} options.title - 表格标题
             * @param {number} [options.titleLevel=4] - 标题级别（1-6）
             * @param {string} [options.idPrefix] - ID前缀，用于生成单元格ID
             * @param {string[]} [options.headers=['类别','值']] - 表头数组
             * @param {string} [options.tableId] - 表格容器的ID
             * @param {string} [options.tableClass='sysinfo-table'] - 表格类名
             * @returns {string} 生成的完整表格HTML
             */
            function generateDataTable(data, options = {}) {
                // 默认值处理
                const {
                    title = '',
                    titleLevel = 4,
                    idPrefix = 'table',
                    headers = ['类别', '值'],
                    tableId = '',
                    tableClass = 'sysinfo-table'
                } = options;
                // 生成表格行
                const rows = Object.entries(data).map(([key, value]) => {
                    const label = AppConfig.operationKeyMap[key] || key;
                    return `
                  <tr>
                      <td>${label}</td>
                      <td>
                          <div class="${AppConfig.cssClasses.editableCell} ${AppConfig.cssClasses.autoData}" id="${idPrefix}-${key}" contenteditable="true">${value}</div>
                      </td>
                  </tr>`;
                }).join('');
                // 生成完整表格容器
                return `
                  ${title ? `<h${titleLevel} id="${tableId || idPrefix + '-title'}">${title}</h${titleLevel}>` : ''}
                  <div class="table-container">
                    <table class="${tableClass}">
                      <tr>${headers.map(header => `<th>${header}</th>`).join('')}</tr>
                      ${rows}
                    </table>
                  </div>
              `;
            }
            /**
             * 生成联系信息项的HTML。
             * @param {string} label - 标签文本。
             * @param {string} id - 元素ID。
             * @param {string} value - 默认值。
             * @param {string} [icon=''] - FontAwesome图标类名。
             * @returns {string} 生成的HTML字符串。
             */
            function generateContactItem(label, id, value, icon = '') {
                const iconHtml = icon ? `<i class="${icon}"></i>` : '';
                return `
              <div class="contact-item">
                  ${iconHtml}
                  <div class="contact-label">${label}:</div>
                  <div class="${AppConfig.cssClasses.contactValue}" id="${id}" contenteditable="true">${value}</div>
              </div>`;
            }
            /**
             * 生成目录项的DOM元素。
             * @param {number} level - 目录层级。
             * @param {string} text - 显示的文本。
             * @param {string} targetId - 对应的页面内容锚点ID。
             * @returns {HTMLElement} 生成的div元素。
             */
            function generateDirectoryItem(level, text, targetId) {
                const item = document.createElement('div');
                item.className = `${AppConfig.cssClasses.directoryItem} level${level}`;
                item.dataset.level = level;
                item.dataset.target = targetId;
                const icon = document.createElement('span');
                icon.className = 'toggle-icon';
                icon.innerHTML = '<i class="fas fa-chevron-down"></i>';
                item.appendChild(icon);
                const textNode = document.createTextNode(text);
                item.appendChild(textNode);
                return item;
            }
            /**
             * 异步地动态生成文档目录 (Table of Contents)。
             * 此函数会扫描内容区域的所有标题标签 (h1-h6)，根据它们的层级关系构建一个可交互的、
             * 支持折叠和展开的树形目录，并将其添加到渲染队列中执行。
             * @public
             * @returns {void}
             */
            function generateDynamicToc() {
                const task = () => {
                    const content = DOMUtils.getElement('.content');
                    const headings = Array.from(content.querySelectorAll('h1, h2, h3, h4, h5, h6'));
                    const directoryContainer = DOMUtils.getElement(AppConfig.selectors.directory);
                    directoryContainer.innerHTML = '';
                    const root = {
                        level: 0,
                        children: []
                    };
                    const stack = [root];
                    headings.forEach((heading, index) => {
                        if (!heading.id) {
                            heading.id = `heading-${index}`;
                        }
                        const level = parseInt(heading.tagName.substring(1));
                        const node = {
                            heading,
                            level,
                            children: []
                        };
                        while (stack.length > 1 && stack[stack.length - 1].level >= level) {
                            stack.pop();
                        }
                        const parent = stack[stack.length - 1];
                        parent.children.push(node);
                        stack.push(node);
                    });
                    /**
                     * 递归地将标题树构建为DOM元素并附加到父容器中。
                     * @param {object} node - 树的当前节点。
                     * @param {HTMLElement} parentElement - 用于附加子项的DOM容器。
                     * @param {number} depth - 当前递归深度。
                     */
                    function buildToc(node, parentElement, depth = 0) {
                        node.children.forEach((child, index) => {
                            const isFirstSection = depth === 0 && index === 0;
                            // 直接使用HTML中的原始文本，不再添加任何序号
                            let displayText = child.heading.textContent.trim();
                            const tocItem = HTMLGenerator.generateDirectoryItem(depth + 1, displayText,
                                child.heading.id);
                            parentElement.appendChild(tocItem);
                            const childrenContainer = document.createElement('div');
                            childrenContainer.className = AppConfig.cssClasses.children;
                            if (isFirstSection && depth === 0) {
                                childrenContainer.classList.add(AppConfig.cssClasses.expanded);
                            } else {
                                childrenContainer.classList.add(AppConfig.cssClasses.collapsed);
                                childrenContainer.style.maxHeight = '0';
                                childrenContainer.style.opacity = '0';
                            }
                            parentElement.appendChild(childrenContainer);
                            const icon = tocItem.querySelector('.toggle-icon');
                            if (icon && !(isFirstSection && depth === 0)) {
                                icon.style.transform = 'rotate(-90deg)';
                            }
                            if (child.children.length > 0) {
                                buildToc(child, childrenContainer, depth + 1);
                            }
                        });
                    }
                    buildToc(root, directoryContainer);
                };
                renderManager.addTask(task);
            }
            return {
                generateDataTable,
                resetSectionCounters,
                generateContactItem,
                generateDirectoryItem,
                generateDynamicToc,
            };
        })();

        /**
         * @module DataManager
         * @description 负责应用的数据管理，包括本地存储、数据加载/保存以及获取配置。
         */
        const DataManager = (() => {
            // 本地存储操作
            const storage = {
                /**
                 * 将键值对保存到localStorage。
                 * @param {string} key - 存储的键。
                 * @param {string} value - 存储的值。
                 * @returns {boolean} 如果成功则返回true，否则返回false。
                 */
                save(key, value) {
                    try {
                        localStorage.setItem(key, value);
                        return true;
                    } catch (error) {
                        console.error('保存数据失败:', error);
                        return false;
                    }
                },
                /**
                 * 从localStorage加载数据。
                 * @param {string} key - 要加载的键。
                 * @returns {string|null} 返回加载的值，或在失败时返回null。
                 */
                load(key) {
                    try {
                        return localStorage.getItem(key);
                    } catch (error) {
                        console.error('加载数据失败:', error);
                        return null;
                    }
                },
                /**
                 * 从localStorage移除数据。
                 * @param {string} key - 要移除的键。
                 * @returns {boolean} 如果成功则返回true，否则返回false。
                 */
                remove(key) {
                    try {
                        localStorage.removeItem(key);
                        return true;
                    } catch (error) {
                        console.error('删除数据失败:', error);
                        return false;
                    }
                },
                /**
                 * 清空所有localStorage数据。
                 * @returns {boolean} 如果成功则返回true，否则返回false。
                 */
                clear() {
                    try {
                        localStorage.clear();
                        return true;
                    } catch (error) {
                        console.error('清空数据失败:', error);
                        return false;
                    }
                }
            };
            /**
             * 保存页面上所有可编辑元素的内容到localStorage。
             * @returns {{savedCount: number, errors: Array<string>, totalElements: number}} 返回保存结果的统计对象。
             */
            function saveAllData() {
                // 强制清除缓存并重新获取元素，避免获取到空的缓存结果
                DOMUtils.clearCache();
                // 直接使用 document.querySelectorAll 确保获取最新的DOM元素
                const editableElements = document.querySelectorAll('.editable-cell, .contact-value');
                let savedCount = 0;
                const errors = [];
                // 添加调试信息
                console.log(`找到 ${editableElements.length} 个可编辑元素`);
                editableElements.forEach((element, index) => {
                    const id = element.id;
                    if (id) {
                        const content = element.textContent || element.innerText || '';
                        const success = storage.save(id, content);
                        if (success) {
                            savedCount++;
                        } else {
                            errors.push(id);
                        }
                    } else {
                        console.warn(`第 ${index + 1} 个元素缺少 ID 属性:`, element); // 警告日志
                    }
                });
                console.log(`保存完成: 成功 ${savedCount} 个, 失败 ${errors.length} 个`);
                return {
                    savedCount,
                    errors,
                    totalElements: editableElements.length
                };
            }
            /**
            * 检测当前页面是否为导出版本
            * @returns {boolean} 如果是导出版本返回true，否则返回false
            */
            function isExportedVersion() {
                const exportMeta = document.querySelector('meta[name="export-version"]');
                return exportMeta && exportMeta.getAttribute('content') === 'true';
            }
            /**
             * 从localStorage加载数据并填充到页面上所有可编辑元素。
             * @returns {number} 返回成功加载的数据项数量。
             */
            function loadAllData() {
                // *** 新增：如果是导出版本，跳过从缓存加载数据 ***
                if (isExportedVersion()) {
                    console.log('检测到导出版本，跳过从缓存加载数据');
                    return 0;
                }
                const editableElements = DOMUtils.getElements('.editable-cell, .contact-value');
                let loadedCount = 0;
                editableElements.forEach(element => {
                    const id = element.id;
                    if (id) {
                        const value = storage.load(id);
                        if (value !== null) {
                            element.textContent = value;
                            loadedCount++;
                        }
                    }
                });
                return loadedCount;
            }
            /**
             * 从项目数据中获取当前的数据库安装模式。
             * @returns {string} 返回安装模式字符串 (如 'single', 'datawatch')。
             */
            function getInstallMode() {
                const installMode = projectData.common.dmInstallMode;
                return AppConfig.installModes.includes(installMode) ? installMode : 'single';
            }
            return {
                storage,
                saveAllData,
                loadAllData,
                getInstallMode,
                isExportedVersion  // *** 新增导出函数 ***
            };
        })();

        /**
         * @module EventManager
         * @description 管理应用中的所有事件监听和处理，如事件委托、自动保存、目录交互等。
         */
        const EventManager = (() => {
            /**
             * 实现事件委托，将事件处理器绑定到父元素上，以高效地处理子孙元素的事件。
             * @param {Element} parent - 监听事件的父元素。
             * @param {string} selector - 用于匹配目标子孙元素的CSS选择器。
             * @param {string} eventType - 要监听的事件类型 (例如 'click', 'input')。
             * @param {Function} handler - 当事件在匹配的元素上触发时执行的回调函数。
             * @returns {void}
             */
            function delegate(parent, selector, eventType, handler) {
                parent.addEventListener(eventType, function (e) {
                    const target = e.target.closest(selector);
                    if (target && parent.contains(target)) {
                        handler.call(target, e);
                    }
                });
            }
            /**
             * 为所有可编辑元素绑定自动保存事件。
             * 对 'input' 事件使用防抖（debounce）以优化性能，对 'blur' 事件则立即保存。
             * @returns {void}
             */
            function bindAutoSaveEvents() {
                const debouncedSave = DOMUtils.debounce((element) => {
                    const id = element.id;
                    if (id) {
                        DataManager.storage.save(id, element.textContent);
                    }
                }, AppConfig.performance.saveDebounceDelay);
                // 使用事件委托为所有可编辑元素绑定 'input' 事件
                delegate(document.body, '.editable-cell, .contact-value', 'input', function (e) {
                    debouncedSave(this);
                });
                // 使用事件委托为所有可编辑元素绑定 'blur' (失焦) 事件
                delegate(document.body, '.editable-cell, .contact-value', 'blur', function (e) {
                    const id = this.id;
                    if (id) {
                        DataManager.storage.save(id, this.textContent);
                    }
                });
            }
            /**
             * 为目录（Table of Contents）区域绑定点击事件，以实现交互功能。
             * @returns {void}
             */
            function bindDirectoryEvents() {
                const directory = DOMUtils.getElement(AppConfig.selectors.directory);
                if (directory) {
                    delegate(directory, '.directory-item', 'click', function (e) {
                        e.stopPropagation(); // 防止事件冒泡干扰
                        handleDirectoryItemClick(this);
                    });
                }
            }
            /**
             * 处理目录项的点击事件，负责展开/折叠子菜单和滚动到对应内容锚点。
             * @param {HTMLElement} target - 被点击的目录项元素。
             * @returns {void}
             */
            function handleDirectoryItemClick(target) {
                const childrenContainer = target.nextElementSibling;
                // 切换子菜单展开/折叠
                if (childrenContainer && childrenContainer.classList.contains(AppConfig.cssClasses.children)) {
                    const isCurrentlyExpanded = childrenContainer.classList.contains(AppConfig.cssClasses.expanded);
                    if (isCurrentlyExpanded) {
                        // 折叠
                        childrenContainer.classList.remove(AppConfig.cssClasses.expanded);
                        childrenContainer.classList.add(AppConfig.cssClasses.collapsed);
                        childrenContainer.style.maxHeight = '0';
                        childrenContainer.style.opacity = '0';
                    } else {
                        // 展开
                        childrenContainer.classList.remove(AppConfig.cssClasses.collapsed);
                        childrenContainer.classList.add(AppConfig.cssClasses.expanded);
                        childrenContainer.style.maxHeight = '2000px';
                        childrenContainer.style.opacity = '1';
                    }
                    // 更新图标状态
                    const icon = target.querySelector('.toggle-icon');
                    if (icon) {
                        const isExpanded = childrenContainer.classList.contains(AppConfig.cssClasses.expanded);
                        icon.style.transform = isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)';
                    }
                }
                // 滚动到目标内容位置
                const targetId = target.dataset.target;
                if (targetId) {
                    scrollToTarget(targetId);
                    setActiveMenuItem(target);
                }
            }
            /**
             * 绑定联系信息同步事件。
             * 当主内容区的联系人信息被编辑时，实时同步更新侧边栏对应的联系信息。
             * @returns {void}
             */
            function bindContactSyncEvents() {
                const supportContainer = DOMUtils.getElement(AppConfig.selectors.supportContainer);
                if (supportContainer) {
                    delegate(supportContainer, '.contact-value', 'input', function (e) {
                        const id = this.id;
                        const value = this.textContent;
                        const sidebarElement = DOMUtils.getElement(`#${id}-sidebar`);
                        if (sidebarElement) {
                            sidebarElement.textContent = value;
                        }
                    });
                }
            }
            /**
             * (节流版) 平滑滚动到页面上指定ID的元素位置。
             * 使用节流（throttle）防止高频触发，并向上偏移100px以避开顶部导航栏。
             * @param {string} targetId - 目标元素的ID。
             * @returns {void}
             */
            const scrollToTarget = DOMUtils.throttle((targetId) => {
                const targetElement = DOMUtils.getElement(`#${targetId}`);
                if (targetElement) {
                    const offsetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset -
                        100;
                    window.scrollTo({
                        top: offsetPosition,
                        behavior: 'smooth'
                    });
                }
            }, AppConfig.performance.scrollThrottleDelay);
            /**
             * 设置当前活动的目录项，通过添加CSS类来高亮显示，并移除其他项的高亮。
             * @param {HTMLElement} clickedItem - 用户当前点击的目录项元素。
             * @returns {void}
             */
            function setActiveMenuItem(clickedItem) {
                const allItems = DOMUtils.getElements('.directory-item');
                allItems.forEach(el => el.classList.remove(AppConfig.cssClasses.active));
                clickedItem.classList.add(AppConfig.cssClasses.active);
            }
            return {
                delegate,
                bindAutoSaveEvents,
                bindDirectoryEvents,
                bindContactSyncEvents,
                scrollToTarget,
                setActiveMenuItem
            };
        })();

        /**
         * @module Renderer
         * @description 负责将数据渲染成HTML并插入到页面中，包含一个渲染队列管理器以优化性能。
         */
        const Renderer = (() => {
            /**
             * @class RenderManager
             * @description 一个用于管理和调度渲染任务的类。
             */
            class RenderManager {
                constructor() {
                    this.renderQueue = [];
                    this.isRendering = false;
                }
                addTask(task) {
                    this.renderQueue.push(task);
                    if (!this.isRendering) {
                        this.processQueue();
                    }
                }
                async processQueue() {
                    this.isRendering = true;
                    while (this.renderQueue.length > 0) {
                        const task = this.renderQueue.shift();
                        try {
                            await task();
                        } catch (error) {
                            console.error('渲染任务执行失败:', error);
                        }
                        await this.nextTick();
                    }
                    this.isRendering = false;
                }
                nextTick() {
                    return new Promise(resolve => requestAnimationFrame(resolve));
                }
            }
            const renderManager = new RenderManager();
            /**
             * 渲染项目信息部分。
             * @returns {void}
             */
            function renderProjectInfo() {
                const task = () => {
                    const { common, host, database } = projectData;
                    const container = DOMUtils.getElement('#section1');
                    const html = `
                  <h2 id="section1-title">1. 项目信息</h2>
                  ${HTMLGenerator.generateDataTable(common, {
                        title: '1.1. 项目信息',
                        titleLevel: 3,
                        idPrefix: 'project',
                        tableId: 'project-info'
                    })}
                  <h3 id="deploy-info">1.2. 数据库信息</h3>
                  ${HTMLGenerator.generateDataTable(host, {
                        title: '1.2.1. 主机登录信息',
                        titleLevel: 4,
                        idPrefix: 'host',
                        tableId: 'host-info'
                    })}
                  ${HTMLGenerator.generateDataTable(database, {
                        title: '1.2.2. 数据库登录信息',
                        titleLevel: 4,
                        idPrefix: 'db',
                        tableId: 'db-info'
                    })}
              `;
                    container.innerHTML = html;
                };
                renderManager.addTask(task);
            }
            /**
             * 生成节点的操作系统信息部分的完整HTML。
             * @private
             * @param {object} node - 当前节点的数据对象。
             * @param {number} nodeIndex - 当前节点的索引。
             * @param {number} sectionNumber - 当前节点的主章节编号。
             * @returns {string} 节点的操作系统信息部分的HTML字符串。
             */
            function generateNodeOsInfo(node, nodeIndex, sectionNumber) {
                HTMLGenerator.resetSectionCounters();
                return `
              <h3 id="server-info-${nodeIndex}">${sectionNumber}.1. 操作系统信息</h3>
              <p>为了稳定高效的运行，DM数据库有特定的软件和硬件的要求。下面总结了数据库环境的节点信息，以下列出系统主机的主要配置情况：</p>
              
              ${HTMLGenerator.generateDataTable(node.serverInfo, {
                    title: `${sectionNumber}.1.1. 主机信息`,
                    titleLevel: 4,
                    idPrefix: `server-info-${nodeIndex}`,
                    tableId: `host-details-${nodeIndex}`
                })}
              
              <h4 id="system-config-${nodeIndex}">${sectionNumber}.1.2. 系统配置信息</h4>
              ${HTMLGenerator.generateDataTable({ 'CPU信息': node.systemConfig.cpuInfoDetail }, {
                    title: `${sectionNumber}.1.2.1. CPU信息`,
                    titleLevel: 5,
                    idPrefix: `cpu-info-${nodeIndex}`,
                    tableId: `cpu-info-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '内存信息': node.systemConfig.memoryInfoDetail }, {
                    title: `${sectionNumber}.1.2.2. 内存信息`,
                    titleLevel: 5,
                    idPrefix: `memory-info-${nodeIndex}`,
                    tableId: `memory-info-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '网卡信息': node.systemConfig.networkInfoDetail }, {
                    title: `${sectionNumber}.1.2.3. 网卡信息`,
                    titleLevel: 5,
                    idPrefix: `network-info-${nodeIndex}`,
                    tableId: `network-info-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '内核参数': node.systemConfig.kernelParamsDetail }, {
                    title: `${sectionNumber}.1.2.4. 内核参数`,
                    titleLevel: 5,
                    idPrefix: `kernel-params-${nodeIndex}`,
                    tableId: `kernel-params-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '用户资源': node.systemConfig.userResourcesDetail }, {
                    title: `${sectionNumber}.1.2.5. 用户资源`,
                    titleLevel: 5,
                    idPrefix: `user-resources-${nodeIndex}`,
                    tableId: `user-resources-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '文件系统': node.systemConfig.filesystemDetail }, {
                    title: `${sectionNumber}.1.2.6. 文件系统`,
                    titleLevel: 5,
                    idPrefix: `file-system-${nodeIndex}`,
                    tableId: `file-system-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${generateSecurityConfigHtml(node.systemConfig, nodeIndex, sectionNumber)}
              ${HTMLGenerator.generateDataTable({ '磁盘调度算法': node.systemConfig.scheduleDetail }, {
                    title: `${sectionNumber}.1.2.8. 磁盘调度算法`,
                    titleLevel: 5,
                    idPrefix: `disk-scheduler-${nodeIndex}`,
                    tableId: `disk-scheduler-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '系统资源': node.systemConfig.systemDetail }, {
                    title: `${sectionNumber}.1.2.9. 系统资源`,
                    titleLevel: 5,
                    idPrefix: `system-resources-${nodeIndex}`,
                    tableId: `system-resources-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '登录资源限制': node.systemConfig.loginResourcesDetail }, {
                    title: `${sectionNumber}.1.2.10. 登录资源限制`,
                    titleLevel: 5,
                    idPrefix: `login-limits-${nodeIndex}`,
                    tableId: `login-limits-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${HTMLGenerator.generateDataTable({ '全局环境变量': node.systemConfig.profile }, {
                    title: `${sectionNumber}.1.2.11. 全局环境变量`,
                    titleLevel: 5,
                    idPrefix: `global-env-vars-${nodeIndex}`,
                    tableId: `global-env-vars-${nodeIndex}`,
                    headers: ['类型', '值']
                })}
              ${generateUserEnvConfigHtml(node.systemConfig, nodeIndex, sectionNumber)}
          `;
            }
            /**
             * 生成安全配置（防火墙和SELinux）部分的HTML表格。
             * @private
             * @param {object} config - 包含安全配置信息的对象。
             * @param {number} index - 节点的索引，用于生成唯一的元素ID。
             * @param {number} sectionNumber - 当前主章节编号。
             * @returns {string} 安全配置部分的HTML字符串。
             */
            function generateSecurityConfigHtml(config, index, sectionNumber) {
                const securityData = {
                    '防火墙端口': config.firewallPortDetail,
                    'SELinux状态': config.selinuxDetail
                };
                return HTMLGenerator.generateDataTable(securityData, {
                    title: `${sectionNumber}.1.2.7. 安全配置`,
                    titleLevel: 5,
                    idPrefix: `security-config-${index}`,
                    tableId: `security-config-${index}`,
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成用户环境变量配置部分的HTML表格。
             * @private
             * @param {object} config - 包含用户环境变量信息的对象。
             * @param {number} index - 节点的索引，用于生成唯一的元素ID。
             * @param {number} sectionNumber - 当前主章节编号。
             * @returns {string} 用户环境变量配置部分的HTML字符串。
             */
            function generateUserEnvConfigHtml(config, index, sectionNumber) {
                const envData = {
                    'root用户环境变量': config.rootEnv,
                    'dmdba用户环境变量': config.dmdbaEnv
                };
                return HTMLGenerator.generateDataTable(envData, {
                    title: `${sectionNumber}.1.2.12. 用户环境变量配置`,
                    titleLevel: 5,
                    idPrefix: `user-env-config-${index}`,
                    tableId: `user-env-config-${index}`,
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成节点的数据库核心信息部分的HTML。
             * @private
             * @param {object} node - 当前节点的数据对象。
             * @param {number} nodeIndex - 当前节点的索引。
             * @param {number} sectionNumber - 当前节点的主章节编号。
             * @returns {string} 节点的数据库核心信息部分的HTML字符串。
             */
            function generateNodeDbInfo(node, nodeIndex, sectionNumber) {
                return `
              <h3 id="database-info-${nodeIndex}">${sectionNumber}.2. 数据库信息</h3>
 
              ${HTMLGenerator.generateDataTable(node.license, {
                    title: `${sectionNumber}.2.1. 授权信息`,
                    titleLevel: 4,
                    idPrefix: `license-${nodeIndex}`,
                    tableId: `license-info-${nodeIndex}`
                })}              

			  ${HTMLGenerator.generateDataTable(node.databaseInstance, {
                    title: `${sectionNumber}.2.2. 数据库实例信息`,
                    titleLevel: 4,
                    idPrefix: `db-${nodeIndex}`,
                    tableId: `ins-info-${nodeIndex}`
                })}
                
              ${HTMLGenerator.generateDataTable(node.directories, {
                    title: `${sectionNumber}.2.3. 目录信息`,
                    titleLevel: 4,
                    idPrefix: `dir-${nodeIndex}`,
                    tableId: `directories-${nodeIndex}`
                })}
				
			  ${HTMLGenerator.generateDataTable(node.configFiles, {
                    title: `${sectionNumber}.2.4. 数据库配置文件`,
                    titleLevel: 4,
                    idPrefix: `config-files-${nodeIndex}`,
                    tableId: `db-ini-${nodeIndex}`,
                    headers: ['配置文件', '值']
                })}
				
          `;
            }
            /**
             * 为特定集群模式生成数据库备份还原和模式修改步骤的HTML表格。
             * @private
             * @param {object} node - 当前节点的数据对象。
             * @param {number} nodeIndex - 当前节点的索引。
             * @param {number} sectionNumber - 当前节点的主章节编号。
             * @returns {string} 包含备份还原和模式修改步骤的HTML字符串。
             */
            function generateNodeDbConf(node, nodeIndex, sectionNumber) {
                const installMode = DataManager.getInstallMode();
                if (installMode !== 'datawatch') return '';
                const bakData = {
                    '备份还原': node.databaseBak.dmBak
                };
                const modeSteps = {
                    '1. 启动数据库到mount状态': '启动数据库至mount状态，准备执行数据库模式修改操作。',
                    '2. 修改数据库模式': node.databaseBak.dmMode,
                    '3. 启动数据守护进程': '启动数据守护进程以确保数据库的正常运行。'
                };
                return `
              ${HTMLGenerator.generateDataTable(bakData, {
                    title: `${sectionNumber}.2.5. 备份还原`,
                    titleLevel: 4,
                    idPrefix: `db-bak-${nodeIndex}`,
                    tableId: `database-bak-${nodeIndex}`,
                    headers: ['备份还原', '命令']
                })}
              ${HTMLGenerator.generateDataTable(modeSteps, {
                    title: `${sectionNumber}.2.6. 修改数据库模式并启动`,
                    titleLevel: 4,
                    idPrefix: `db-mode-${nodeIndex}`,
                    tableId: `database-mode-${nodeIndex}`,
                    headers: ['步骤', '值']
                })}
          `;
            }
            /**
             * 生成单个节点的完整HTML内容。
             * @private
             * @param {object} node - 当前节点的数据对象。
             * @param {number} nodeIndex - 当前节点的索引（从0开始）。
             * @param {number} sectionNumber - 当前节点在文档中的主章节编号。
             * @param {string} serverIp - 当前节点的服务器IP地址，用作章节标题。
             * @returns {string} 包含单个节点所有信息的完整HTML字符串。
             */
            function generateNodeHtml(node, nodeIndex, sectionNumber, serverIp) {
                return `
              <h2>${sectionNumber}. ${serverIp}</h2>
              ${generateNodeOsInfo(node, nodeIndex, sectionNumber)}
              ${generateNodeDbInfo(node, nodeIndex, sectionNumber)}
              ${generateNodeDbConf(node, nodeIndex, sectionNumber)}
          `;
            }
            /**
             * 渲染所有节点信息部分。
             * @returns {void}
             */
            function renderNodes() {
                // 创建一个任务，任务的内容是渲染节点
                const task = () => {
                    // 获取所有节点数据
                    const nodes = projectData.nodes;
                    // 获取节点对象的键，并按字母顺序排序
                    const nodeKeys = Object.keys(nodes).sort();
                    // 获取节点容器的 DOM 元素
                    const container = DOMUtils.getElement(AppConfig.selectors.nodesContainer);
                    // 创建一个文档片段，用于批量操作 DOM 元素
                    const fragment = DOMUtils.createFragment();
                    // 遍历所有节点的键，生成节点的 HTML 并插入到文档片段中
                    nodeKeys.forEach((nodeKey, i) => {
                        const node = nodes[nodeKey];
                        // 为每个节点分配一个区块编号
                        const sectionNumber = i + 2;  // 假设区块编号从2开始
                        // 获取该节点的服务器 IP
                        const serverIp = node.serverInfo.serverIp;
                        // 创建一个新的 div 元素，用作节点的容器
                        const section = document.createElement('div');
                        section.className = 'section';  // 为该 div 设置样式类名
                        section.id = `section${sectionNumber}`;  // 为该 div 设置唯一的 ID
                        // 生成该节点的 HTML 内容并插入到 section 中
                        section.innerHTML = generateNodeHtml(node, i, sectionNumber, serverIp);
                        // 将创建的 section 添加到文档片段中
                        fragment.appendChild(section);
                    });
                    // 将文档片段的内容插入到容器中
                    container.appendChild(fragment);
                };
                // 将该任务添加到渲染管理器的任务队列中
                renderManager.addTask(task);
            }
            /**
             * 生成单机模式启停内容
             * @param {object} operations - 操作指令对象
             * @param {string} subsectionNumber - 子章节编号
             * @returns {string} HTML字符串
             */
            function generateSingleModeStartup(operations, subsectionNumber) {
                return HTMLGenerator.generateDataTable(operations.single, {
                    title: `${subsectionNumber}.1. 单机数据库启停`,
                    titleLevel: 4,
                    idPrefix: 'operations-single',
                    tableId: 'single-startup',
                    headers: ['操作', '说明']
                });
            }
            /**
             * 生成集群模式启停内容
             * @param {object} operations - 操作指令对象
             * @param {string} subsectionNumber - 子章节编号
             * @param {string} installMode - 安装模式
             * @returns {string} HTML字符串
             */
            function generateClusterModeStartup(operations, subsectionNumber, installMode) {
                const clusterNames = {
                    'datawatch': 'Datawatch 集群',
                    'raft': 'Raft 集群',
                    'dsc': 'DSC 集群',
                    'dscm': 'DSC(ASM镜像) 集群'
                };
                const clusterName = clusterNames[installMode] || '集群';
                const clusterOpsData = operations[installMode];
                let content = HTMLGenerator.generateDataTable(clusterOpsData, {
                    title: `${subsectionNumber}.1. ${clusterName}启停`,
                    titleLevel: 4,
                    idPrefix: `operations-${installMode}`,
                    tableId: `${installMode}-startup`,
                    headers: ['操作', '说明']
                });
                content += generateHAAndRWConfig(subsectionNumber, installMode);
                return content;
            }
            /**
             * 生成合并后的高可用和读写分离配置HTML
             * @param {string} sectionNumber 主章节编号 (如"3.5")
             * @param {string} installMode 安装模式
             * @returns {string} 生成的HTML
             */
            function generateHAAndRWConfig(sectionNumber, installMode) {
                if (!sectionNumber || !installMode) return '';
                const { database } = projectData;
                const config = projectData.clusterConfigs[installMode];
                if (!config) return '';
                // 高可用基础配置
                const haConfigCommands = {
                    [AppConfig.operationKeyMap.dmSvcConf]: config.configParams.join('\n'),
                    [AppConfig.operationKeyMap.appConnConf]: AppConfig.haConfig.connectionTemplate.replace('{{sysdbaPassword}}', database.sysdbaPassword)
                };
                // 读写分离配置
                const rwConfigCommands = {
                    [AppConfig.operationKeyMap.dmSvcConfRW]: [...config.configParams, ...config.rwSeparateParams].join('\n'),
                    [AppConfig.operationKeyMap.appConnConfRW]: AppConfig.haConfig.connectionTemplate.replace('{{sysdbaPassword}}', database.sysdbaPassword)
                };
                return `
                  <h4>${sectionNumber}.2. 高可用和读写分离配置</h4>
                  <p><strong>1. 文件存放位置说明</strong></p>
                  <div class="note">${AppConfig.haConfig.fileLocationInfo}</div>
                  
                  <p><strong>2. 高可用配置</strong></p>
                  ${HTMLGenerator.generateDataTable(haConfigCommands, {
                    headers: ['配置类型', '配置内容']
                })}
                  
                  <p><strong>3. 读写分离配置</strong></p>
                  ${HTMLGenerator.generateDataTable(rwConfigCommands, {
                    headers: ['配置类型', '配置内容']
                })}
                  
                  <p><strong>4. 集群连接说明</strong></p>
                  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${AppConfig.haConfig.connectionInfo}</p>
                `;
            }
            /**
             * 生成3.1节：数据库启停管理
             * @param {object} operations - 操作指令对象
             * @param {number} sectionNumber - 主章节编号
             * @param {string} installMode - 安装模式
             * @returns {string} HTML字符串
             */
            function generateDatabaseStartupSection(operations, sectionNumber, installMode) {
                const subsectionNumber = `${sectionNumber}.1`;
                let startupContent = '';
                if (installMode === 'single') {
                    startupContent = generateSingleModeStartup(operations, subsectionNumber);
                } else {
                    startupContent = generateClusterModeStartup(operations, subsectionNumber, installMode);
                }
                return `
              <h3 id="database-startup">${subsectionNumber}. 数据库运维和使用</h3>
              ${startupContent}
          `;
            }
            /**
             * 生成3.2节：创建表空间和用户
             * @param {number} sectionNumber - 主章节编号
             * @returns {string} HTML字符串
             */
            function generateTablespaceUserSection(sectionNumber) {
                const { operationCommands } = projectData;
                const subsectionNumber = `${sectionNumber}.2`;
                return HTMLGenerator.generateDataTable(operationCommands.tablespaceUser, {
                    title: `${subsectionNumber}. 创建表空间和用户`,
                    titleLevel: 3,
                    idPrefix: 'tablespace-user',
                    tableId: 'tablespace-user',
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成3.3节：维护联机日志
             * @param {number} sectionNumber - 主章节编号
             * @returns {string} HTML字符串
             */
            function generateLogManagementSection(sectionNumber) {
                const { operationCommands } = projectData;
                const subsectionNumber = `${sectionNumber}.3`;
                return HTMLGenerator.generateDataTable(operationCommands.logManagement, {
                    title: `${subsectionNumber}. 维护联机日志`,
                    titleLevel: 3,
                    idPrefix: 'log-management',
                    tableId: 'log-management',
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成3.4节：授权管理
             * @param {number} sectionNumber - 主章节编号
             * @returns {string} HTML字符串
             */
            function generateLicenseManagementSection(sectionNumber) {
                const { operationCommands } = projectData;
                const subsectionNumber = `${sectionNumber}.4`;
                return HTMLGenerator.generateDataTable(operationCommands.licenseManagement, {
                    title: `${subsectionNumber}. 授权管理`,
                    titleLevel: 3,
                    idPrefix: 'license-management',
                    tableId: 'license-management',
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成3.5节：配置作业备份
             * @param {number} sectionNumber - 主章节编号
             * @returns {string} HTML字符串
             */
            function generateBackupJobSection(sectionNumber) {
                const { operationCommands } = projectData;
                const subsectionNumber = `${sectionNumber}.5`;
                return HTMLGenerator.generateDataTable(operationCommands.backupJob, {
                    title: `${subsectionNumber}. 配置作业备份`,
                    titleLevel: 3,
                    idPrefix: 'backup-job',
                    tableId: 'backup-job',
                    headers: ['类型', '值']
                });
            }
            /**
             * 生成数据守护集群管理内容
             * @param {string} subsectionNumber - 子章节编号
             * @returns {string} HTML字符串
             */
            function generateDataWatchClusterManagement(subsectionNumber) {
                const { statusMonitoring, failoverCommands } = projectData.operationCommands;
                // 生成状态检查表格
                const statusTable = HTMLGenerator.generateDataTable(statusMonitoring, {
                    title: `${subsectionNumber}.1. 集群状态检查`,
                    titleLevel: 4,
                    idPrefix: 'datawatch-status',
                    tableId: 'datawatch-status-check',
                    headers: ['类型', '值']
                });
                // 生成主备切换表格
                const switchoverTable = HTMLGenerator.generateDataTable(failoverCommands, {
                    title: `${subsectionNumber}.2. 主备切换`,
                    titleLevel: 4,
                    idPrefix: 'datawatch-switch',
                    tableId: 'datawatch-switchover',
                    headers: ['类型', '值']
                });
                // 拼接所有内容
                return `
                  <h3 id="datawatch-cluster-management">${subsectionNumber}. 数据守护集群管理</h3>
                  <div class="important">
                      <p>非特殊情况，切勿在业务窗口人工手动切换，切换前请和达梦工程师确定集群状态和切换前置条件</p>
                  </div>
                  ${statusTable}
                  ${switchoverTable}
               `;
            }
            /**
             * 生成其他集群管理内容（预留接口）
             */
            function generateRaftClusterManagement(subsectionNumber) {
                return `
                  <h3 id="raft-cluster-management">${subsectionNumber}. Raft集群管理</h3>
                  <div class="note">
                      <p>Raft集群运维管理功能正在开发中...</p>
                  </div>`;
            }
            function generateDscClusterManagement(subsectionNumber) {
                return `
                  <h3 id="dsc-cluster-management">${subsectionNumber}. DSC集群管理</h3>
                  <div class="note">
                      <p>DSC集群运维管理功能正在开发中...</p>
                  </div>`;
            }
            function generateDscmClusterManagement(subsectionNumber) {
                return `
                  <h3 id="dscm-cluster-management">${subsectionNumber}. DSCM集群管理</h3>
                  <div class="note">
                      <p>DSCM集群运维管理功能正在开发中...</p>
                  </div>`;
            }
            /**
            * 生成集群特定的运维管理内容
            * @param {number} sectionNumber - 主章节编号
            * @param {string} installMode - 安装模式
            * @returns {string} HTML字符串
            */
            function generateClusterSpecificSection(sectionNumber, installMode) {
                if (installMode === 'single') return '';
                const subsectionNumber = `${sectionNumber}.5`;
                switch (installMode) {
                    case 'datawatch':
                        return generateDataWatchClusterManagement(subsectionNumber);
                    case 'raft':
                        return generateRaftClusterManagement(subsectionNumber);
                    case 'dsc':
                        return generateDscClusterManagement(subsectionNumber);
                    case 'dscm':
                        return generateDscmClusterManagement(subsectionNumber);
                    default:
                        return '';
                }
            }
            /**
             * 渲染数据库运维管理部分。
             * @returns {void}
             */
            function renderOperations() {
                const task = () => {
                    const operations = projectData.operations;
                    const actualNodeCount = Object.keys(projectData.nodes).length;
                    const sectionNumber = actualNodeCount + 2;
                    const container = DOMUtils.getElement(AppConfig.selectors.operationsContainer);
                    const installMode = DataManager.getInstallMode();
                    container.innerHTML = `
                  <div class="section" id="section${sectionNumber}">
                      <h2 id="section${sectionNumber}-title">${sectionNumber}. 数据库运维管理</h2>
                      ${generateDatabaseStartupSection(operations, sectionNumber, installMode)}
                      ${generateTablespaceUserSection(sectionNumber)}
                      ${generateLogManagementSection(sectionNumber)}
                      ${generateLicenseManagementSection(sectionNumber)}
                      ${generateBackupJobSection(sectionNumber)}
                      ${generateClusterSpecificSection(sectionNumber, installMode)}
                  </div>`;
                };
                renderManager.addTask(task);
            }
            /**
             * 异步渲染"技术支持"部分。
             * @returns {void}
             */
            function renderSupport() {
                const task = () => {
                    const support = projectData.support;
                    const actualNodeCount = Object.keys(projectData.nodes).length;
                    const sectionNumber = actualNodeCount + 3;
                    const container = DOMUtils.getElement(AppConfig.selectors.supportContainer);
                    if (container) {
                        container.innerHTML = generateSupportHtml(support, sectionNumber);
                        updateSupportSidebar(support);
                    }
                };
                renderManager.addTask(task);
            }
            // 生成技术支持区域的HTML
            function generateSupportHtml(support, sectionNumber) {
                return `
                  <div class="section" id="section${sectionNumber}">
                  	<h2 id="section${sectionNumber}-title">${sectionNumber}. 技术支持</h2>
                  	<div class="contact-info" id="contact">
                  		<div class="contact-grid">
                  			<div class="contact-item">
                  				<div class="contact-label">Author:</div>
                  				<div class="contact-value" id="author" contenteditable="true">${support.author}</div>
                  			</div>
                  			<div class="contact-item">
                  				<div class="contact-label">Mobile:</div>
                  				<div class="contact-value" id="mobile" contenteditable="true">${support.mobile}</div>
                  			</div>
                  			<div class="contact-item">
                  				<div class="contact-label">Mail:</div>
                  				<div class="contact-value" id="email" contenteditable="true">${support.email}</div>
                  			</div>
                  			<div class="contact-item">
                  				<div class="contact-label">微信:</div>
                  				<div class="contact-value" id="wechat" contenteditable="true">${support.wechat}</div>
                  			</div>
                  		</div>
                  		<div class="contact-item" style="margin-top: 20px; background: transparent; padding: 10px 0; box-shadow: none;">
                  			<div class="contact-label">Other:</div>
                  			<div>
                  				<p>官方手册：<span class="contact-value" id="manual" contenteditable="true">${support.manual}</span></p>
                  				<p>官方网站：<span class="contact-value" id="website" contenteditable="true">${support.website}</span></p>
                  				<p>云适配中心：<span class="contact-value" id="eco" contenteditable="true">${support.eco}</span></p>
                  			</div>
                  		</div>
                  	</div>
                  </div>`;
            }
            /**
             * 使用最新的支持信息数据更新侧边栏的联系方式。
             * @private
             * @param {object} support - 包含技术支持联系信息的对象。
             * @returns {void}
             */
            function updateSupportSidebar(support) {
                const sidebar = document.querySelector('.contact-sidebar');
                if (sidebar) {
                    sidebar.innerHTML = `
                        <p><i class="fas fa-user"></i> <span id="author-sidebar">${support.author}</span></p>
                        <p><i class="fas fa-phone"></i> <span id="mobile-sidebar">${support.mobile}</span></p>
                        <p><i class="fas fa-envelope"></i> <span id="email-sidebar">${support.email}</span></p>
                        <p><i class="fas fa-book"></i> <span id="manual-sidebar">${support.manual}</span></p>`;
                }
            }
            /**
             * 异步地动态生成文档目录 (Table of Contents)。
             * 此函数会扫描内容区域的所有标题标签 (h1-h6)，根据它们的层级关系构建一个可交互的、
             * 支持折叠和展开的树形目录，并将其添加到渲染队列中执行。
             * @public
             * @returns {void}
             */
            function generateDynamicToc() {
                const task = () => {
                    const content = DOMUtils.getElement('.content');
                    const headings = Array.from(content.querySelectorAll('h1, h2, h3, h4, h5, h6'));
                    const directoryContainer = DOMUtils.getElement(AppConfig.selectors.directory);
                    directoryContainer.innerHTML = '';
                    const root = {
                        level: 0,
                        children: []
                    };
                    const stack = [root];
                    headings.forEach((heading, index) => {
                        if (!heading.id) {
                            heading.id = `heading-${index}`;
                        }
                        const level = parseInt(heading.tagName.substring(1));
                        const node = {
                            heading,
                            level,
                            children: []
                        };
                        while (stack.length > 1 && stack[stack.length - 1].level >= level) {
                            stack.pop();
                        }
                        const parent = stack[stack.length - 1];
                        parent.children.push(node);
                        stack.push(node);
                    });
                    /**
                     * 递归地将标题树构建为DOM元素并附加到父容器中。
                     * @param {object} node - 树的当前节点。
                     * @param {HTMLElement} parentElement - 用于附加子项的DOM容器。
                     * @param {number} depth - 当前递归深度。
                     */
                    function buildToc(node, parentElement, depth = 0) {
                        node.children.forEach((child, index) => {
                            const isFirstSection = depth === 0 && index === 0;
                            // 直接使用HTML中的原始文本，不再添加任何序号
                            let displayText = child.heading.textContent.trim();
                            const tocItem = HTMLGenerator.generateDirectoryItem(depth + 1, displayText,
                                child.heading.id);
                            parentElement.appendChild(tocItem);
                            const childrenContainer = document.createElement('div');
                            childrenContainer.className = AppConfig.cssClasses.children;
                            if (isFirstSection && depth === 0) {
                                childrenContainer.classList.add(AppConfig.cssClasses.expanded);
                            } else {
                                childrenContainer.classList.add(AppConfig.cssClasses.collapsed);
                                childrenContainer.style.maxHeight = '0';
                                childrenContainer.style.opacity = '0';
                            }
                            parentElement.appendChild(childrenContainer);
                            const icon = tocItem.querySelector('.toggle-icon');
                            if (icon && !(isFirstSection && depth === 0)) {
                                icon.style.transform = 'rotate(-90deg)';
                            }
                            if (child.children.length > 0) {
                                buildToc(child, childrenContainer, depth + 1);
                            }
                        });
                    }
                    buildToc(root, directoryContainer);
                };
                renderManager.addTask(task);
            }
            return {
                renderProjectInfo,
                renderNodes,
                renderOperations,
                renderSupport,
                generateDynamicToc,
                renderManager
            };
        })();

        /**
         * @module App
         * @description 应用的主模块，负责初始化、状态管理和全局功能的协调。
         */
        const App = (() => {
            // 应用状态
            const state = {
                isInitialized: false,
                currentTheme: 'default',
                performance: {
                    startTime: 0,
                    loadTime: 0
                }
            };
            /**
             * 追踪并打印一个函数的执行时间。
             * @param {string} name - 要追踪的名称。
             * @param {Function} fn - 要执行的函数。
             * @returns {*} 返回被执行函数的返回值。
             */
            function trackPerformance(name, fn) {
                const start = performance.now();
                const result = fn();
                const end = performance.now();
                console.log(`${name} 执行时间: ${end - start}ms`);
                return result;
            }
            /**
             * 初始化整个应用程序，包括渲染和事件绑定。
             * @returns {Promise<void>}
             */
            async function initialize() {
                if (state.isInitialized) return;
                state.performance.startTime = performance.now();
                try {
                    // *** 新增：检测是否为导出版本 ***
                    const isExported = DataManager.isExportedVersion();
                    if (isExported) {
                        console.log('当前页面为导出版本，采用静态模式初始化');
                    }
                    // 加载保存的数据（导出版本会自动跳过）
                    await trackPerformance('加载数据', () => {
                        DataManager.loadAllData();
                    });
                    // 渲染各个组件
                    await trackPerformance('渲染项目信息', () => {
                        Renderer.renderProjectInfo();
                    });
                    await trackPerformance('渲染节点信息', () => {
                        Renderer.renderNodes();
                    });
                    await trackPerformance('渲染运维管理', () => {
                        Renderer.renderOperations();
                    });
                    await trackPerformance('渲染技术支持', () => {
                        Renderer.renderSupport();
                    });
                    // 等待渲染完成
                    await Renderer.renderManager.processQueue();
                    // 确保DOM元素已经生成，再清除缓存
                    DOMUtils.clearCache();
                    // 验证关键元素是否存在
                    const editableElements = document.querySelectorAll('.editable-cell, .contact-value');
                    console.log(`初始化完成，共找到 ${editableElements.length} 个可编辑元素`);
                    // 生成目录
                    await trackPerformance('生成目录', () => {
                        Renderer.generateDynamicToc();
                    });
                    // *** 修改：导出版本只绑定必要的事件 ***
                    if (!isExported) {
                        // 原版本绑定所有事件（包括自动保存）
                        await trackPerformance('绑定事件', () => {
                            EventManager.bindAutoSaveEvents();
                            EventManager.bindDirectoryEvents();
                            EventManager.bindContactSyncEvents();
                        });
                    } else {
                        // 导出版本只绑定目录导航事件
                        await trackPerformance('绑定导航事件', () => {
                            EventManager.bindDirectoryEvents();
                        });
                    }
                    // 处理特殊逻辑
                    handleSpecialCases();
                    state.isInitialized = true;
                    state.performance.loadTime = performance.now() - state.performance.startTime;
                    console.log(`应用初始化完成，总耗时: ${state.performance.loadTime}ms`);
                } catch (error) {
                    console.error('初始化失败:', error);
                    const loading = DOMUtils.getElement(AppConfig.selectors.loading);
                    if (loading) {
                        loading.innerHTML = `
                           <div style="color: red; text-align: center;">
                             <h3>初始化错误</h3>
                             <p>${error.message}</p>
                             <button onclick="location.reload()">重新加载</button>
                           </div>
                           `;
                    }
                } finally {
                    // 隐藏加载指示器
                    const loading = DOMUtils.getElement(AppConfig.selectors.loading);
                    if (loading) {
                        loading.style.display = 'none';
                    }
                }
            }
            // 处理特殊情况 - 修复：使用正确的ID前缀
            function handleSpecialCases() {
                const passwordDiv = DOMUtils.getElement('#db-sysssoPassword'); // 修复：正确的ID
                if (passwordDiv && !passwordDiv.textContent.trim()) {
                    passwordDiv.textContent = '企业版禁止登录SYSSSO用户';
                }
            }
            /**
             * 显示一个状态消息条。
             * @param {string} message - 要显示的消息。
             * @param {string} [type='info'] - 消息类型 ('info', 'success', 'warning', 'error')。
             * @param {number} [duration=3000] - 显示时长（毫秒）。
             * @returns {void}
             */
            function showStatus(message, type = 'info', duration = 3000) {
                const statusBar = DOMUtils.getElement(AppConfig.selectors.statusBar);
                if (!statusBar) return;
                statusBar.textContent = message;
                statusBar.className = `status-bar status-${type} no-export`;
                statusBar.style.display = 'block';
                setTimeout(() => {
                    statusBar.style.display = 'none';
                }, duration);
            }
            // 导出功能（优化版）
            async function exportToHTML() {
                try {
                    showStatus('正在生成导出文件...', 'info');
                    // 使用 Web Worker 进行导出处理（如果支持）
                    const exportData = await trackPerformance('导出HTML', () => {
                        return generateExportHTML();
                    });
                    downloadFile(exportData, `达梦数据库部署报告_${getTimestamp()}.html`);
                    showStatus('HTML文件导出成功！', 'success');
                } catch (error) {
                    console.error('导出失败:', error);
                    showStatus('导出失败，请重试！', 'error');
                }
            }
            /**
             * 简单实用的HTML格式化函数
             * @param {string} html - 原始HTML字符串
             * @returns {string} 格式化后的HTML字符串
             */
            // 需要引入js-beautify库
            function formatHTML(html) {
                if (typeof html_beautify === 'undefined') {
                    console.warn('js-beautify库未加载，返回原始HTML');
                    return html;
                }
                try {
                    return html_beautify(html, {
                        indent_size: 2,
                        indent_char: ' ',
                        max_preserve_newlines: 1,
                        preserve_newlines: true,
                        wrap_line_length: 0,
                        indent_inner_html: true
                    });
                } catch (error) {
                    console.error('HTML格式化失败:', error);
                    return html;
                }
            }
            /**
             * 生成用于导出的最终HTML字符串。
             * 该函数会深度克隆当前的DOM，将所有可编辑字段的当前内容同步到克隆的文档中，
             * 然后注入一个小型脚本以保留部分交互功能（如目录滚动），并附加一个导出时间戳。
             * @private
             * @returns {string} 包含了最新数据和内联脚本的完整HTML文档字符串。
             */
            function generateExportHTML() {
                const clonedDoc = document.cloneNode(true);
                // 查找所有带 'no-export' 类的元素并移除它们
                const elementsToRemove = clonedDoc.querySelectorAll('.no-export');
                elementsToRemove.forEach(el => el.remove());
                // *** 新增：添加导出版本标识 ***
                const exportMeta = clonedDoc.createElement('meta');
                exportMeta.setAttribute('name', 'export-version');
                exportMeta.setAttribute('content', 'true');
                clonedDoc.head.appendChild(exportMeta);
                // 1. 同步所有可编辑字段的数据到克隆的文档中
                const originalElements = DOMUtils.getElements('.editable-cell, .contact-value');
                const clonedElements = clonedDoc.querySelectorAll('.editable-cell, .contact-value');
                originalElements.forEach((element, index) => {
                    if (clonedElements[index]) {
                        clonedElements[index].textContent = element.textContent;
                    }
                });
                // 添加导出脚本
                const script = clonedDoc.createElement('script');
                script.textContent = generateExportScript();
                clonedDoc.body.appendChild(script);
                // 4. 在右下角添加一个导出时间信息
                const exportInfo = clonedDoc.createElement('div');
                exportInfo.style.cssText =
                    'position:fixed;bottom:10px;right:25px;background:rgba(0,0,0,0.8);color:white;padding:10px;border-radius:5px;font-size:12px;z-index:1000;';
                exportInfo.innerHTML = `导出时间: ${new Date().toLocaleString('zh-CN')}`;
                clonedDoc.body.appendChild(exportInfo);
                let htmlString = '<!DOCTYPE html>\n' + clonedDoc.documentElement.outerHTML;
                // 格式化HTML代码
                htmlString = formatHTML(htmlString);
                return htmlString;
            }
            // 生成导出脚本
            function generateExportScript() {
                return `
                  document.addEventListener('DOMContentLoaded', function() {
                      // 节流函数
                      function throttle(func, delay) {
                          let timeoutId;
                          let lastExecTime = 0;
                          return function (...args) {
                              const currentTime = Date.now();
                              if (currentTime - lastExecTime > delay) {
                                  func.apply(this, args);
                                  lastExecTime = currentTime;
                              } else {
                                  clearTimeout(timeoutId);
                                  timeoutId = setTimeout(() => {
                                      func.apply(this, args);
                                      lastExecTime = Date.now();
                                  }, delay - (currentTime - lastExecTime));
                              }
                          };
                      }
                      
                      // 滚动到目标位置的函数
                      const scrollToTarget = throttle(function(targetId) {
                          const targetElement = document.querySelector('#' + targetId);
                          if (targetElement) {
                              const offsetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - 100;
                              window.scrollTo({
                                  top: offsetPosition,
                                  behavior: 'smooth'
                              });
                          }
                      }, 100);
                      
                      // 设置活动菜单项
                      function setActiveMenuItem(clickedItem) {
                          const allItems = document.querySelectorAll('.directory-item');
                          allItems.forEach(el => el.classList.remove('active'));
                          clickedItem.classList.add('active');
                      }
                      window.addEventListener('load', function () {
                          document.querySelectorAll('.editable-cell').forEach(function (el) {
                              el.textContent = el.textContent.replace(/^[ 	]+/gm, '');
                          });
                      });
                  });
              `;
            }
            /**
             * 触发浏览器下载给定的内容。
             * @private
             * @param {string} content - 要下载的文件内容（这里是HTML字符串）。
             * @param {string} filename - 下载时默认显示的文件名。
             * @returns {void}
             */
            function downloadFile(content, filename) {
                const blob = new Blob([content], {
                    type: 'text/html;charset=utf-8'
                });
                const url = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.download = filename;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                URL.revokeObjectURL(url); // 释放内存
            }
            /**
             * 获取一个格式化的、适合用作文件名的时间戳字符串。
             * @private
             * @returns {string} 格式如 'YYYY-MM-DDTHH-mm-ss' 的时间戳。
             */
            function getTimestamp() {
                return new Date().toISOString().slice(0, 19).replace(/:/g, '-');
            }
            /**
             * @global
             * @function saveAllData
             * @description 手动触发保存所有可编辑数据到LocalStorage，并显示状态消息。
             * 该函数被暴露到window对象，以便在浏览器控制台或通过UI按钮调用。
             */
            window.saveAllData = () => {
                const result = DataManager.saveAllData();
                let message, type;
                if (result.totalElements === 0) {
                    message = '未找到可保存的数据元素，请确保页面已完全加载';
                    type = 'warning';
                } else if (result.errors.length > 0) {
                    message = `部分数据保存失败！成功: ${result.savedCount}, 失败: ${result.errors.length}`;
                    type = 'warning';
                } else {
                    message = `数据已保存！共保存 ${result.savedCount} 个数据项`;
                    type = 'success';
                }
                showStatus(message, type);
            };
            /**
             * @global
             * @function exportToHTML
             * @description 手动触发将当前页面内容导出为HTML文件的功能。
             * 该函数被暴露到window对象。
             */
            window.exportToHTML = exportToHTML;
            /**
             * @global
             * @function resetAllData
             * @description 重置所有本地存储的数据并刷新页面，会弹出确认框。
             * 该函数被暴露到window对象。
             */
            window.resetAllData = () => {
                if (confirm('确定要重置所有数据吗？这将清除所有本地修改并恢复到初始配置状态。')) {
                    DataManager.storage.clear();
                    location.reload();
                }
            };
            /**
             * @global
             * @function scrollToTop
             * @description 平滑滚动到页面顶部。
             * 该函数被暴露到window对象。
             */
            window.scrollToTop = () => {
                window.scrollTo({
                    top: 0,
                    behavior: 'smooth'
                });
            };
            return {
                initialize,
                showStatus,
                state
            };
        })();
        /**
         * @event DOMContentLoaded
         * @description 应用程序的入口点。
         * 当整个HTML文档被完全加载和解析完成之后，触发App模块的初始化函数，启动整个应用。
         */
        document.addEventListener('DOMContentLoaded', () => {
            App.initialize();
        });
    </script>
</body>

</html>